일반 우선 CSS: 모바일 우선에 대한 새로운 생각
게시 됨: 2022-03-10Ethan Marcotte의 반응형 웹 디자인은 전 세계 웹 개발자에게 반가운 계시였다고 해도 과언이 아닙니다. 이는 완전히 새로운 디자인 사고와 멋진 새로운 프론트 엔드 기술의 물결을 일으켰습니다. 종종 멸시를 받는 m dot 웹사이트의 통치도 끝났습니다. 같은 시대에 Luke Wroblewski의 Mobile First 방법론이 거의 비슷한 영향을 미쳤습니다. 이는 Marcotte의 인상적인 토대를 기반으로 한 확고한 개선이었습니다.
이러한 기술은 대부분의 웹 개발자 생활의 근간을 이루고 있으며 우리에게 많은 도움이 되었지만 안타깝게도 시대는 변하고 개발자는 끊임없이 반복합니다. 방법의 효율성을 높이고 프로젝트 요구 사항이 더 복잡해짐에 따라 새로운 좌절감이 나타납니다.
제네릭 퍼스트를 향한 여정
내가 CSS를 작성하는 방식을 바꾸게 된 원인을 정확히 찾아낼 수는 없습니다. 거의 무의식적으로 일어난 자연스러운 과정이기 때문입니다. 돌이켜보면, 그것은 내가 일하고 있던 개발 환경의 부산물에 가깝다고 생각합니다. 내가 일한 팀은 CSS 선언 내에 중단점을 쉽게 추가할 수 있는 멋진 작은 믹스인을 사용하여 멋진 SCSS 워크플로를 진행하고 있었습니다. 비슷한 기술을 사용하고 있을 것입니다.
이 멋진 작은 SCSS 믹스인은 갑자기 매우 세분화된 미디어 쿼리를 작성하기 쉽게 만들었습니다. 다음과 같이 보이는 가상의 전기 블록을 예로 들어 보겠습니다.
.bio { display: block; width: 100%; background-color: #ece9e9; padding: 20px; margin: 20px 0; @include media('>=small') { max-width: 400px; background-color: white; margin: 20px auto; } @include media('>=medium') { max-width: 600px; padding: 30px; margin: 30px auto; } @include media('>=large') { max-width: 800px; padding: 40px; margin: 40px auto; } @include media('>=huge') { max-width: 1000px; padding: 50px; margin: 50px auto; } }
그림 1. 계단식 미디어 쿼리가 있는 일반적인 모바일 우선
이것은 잘 작동합니다. 저는 과거에 이와 같은 CSS 를 많이 작성했습니다 . 그러나 어느 날 장치 너비가 증가함에 따라 CSS 선언을 덮어쓰는 것이 의미가 없다는 것을 깨달았습니다. 다음 선언에서만 덮어쓰도록 CSS 속성을 선언하는 이유는 무엇입니까?
이것이 내가 그림 1의 예와 같이 위쪽(또는 아래쪽)으로 캐스케이드(cascade)되는 미디어 쿼리의 보다 일반적인 접근 방식과 반대로 구획화된 미디어 쿼리 를 작성하기 시작하게 한 이유입니다.
화면 크기가 증가함에 따라 위로 계단식으로 올라가는 미디어 쿼리를 작성하는 대신 원하는 화면 너비로 스타일을 캡슐화하는 대상 미디어 쿼리를 만들기 시작했습니다. 미디어 쿼리 믹스인은 여기에서 자체적으로 등장할 것입니다. 이제 내 SCSS 미디어 쿼리가 다음과 같이 보이기 시작합니다.
.bio { display: block; width: 100%; padding: 20px; margin: 20px 0; @include media('>=small', ' < medium') { max-width: 400px; margin: 20px auto; } @include media('>=medium', ' < large') { max-width: 600px; padding: 30px; margin: 30px auto; } @include media('>=large', ' < huge') { max-width: 800px; padding: 40px; margin: 40px auto; } @include media('>=huge') { max-width: 1000px; padding: 50px; margin: 50px auto; } }
그림 2. 구획화된 미디어 쿼리의 예
이 새로운 접근 방식은 나에게 더 직관적으로 느껴졌고 이전 중단점에서 스타일을 재설정해야 하는 필요성을 줄였으며 CSS를 읽기 쉽게 만들었습니다. 더 중요한 것은 미디어 쿼리를 보다 의미 있는 방식으로 자체 문서화하는 것이었습니다.
그래도 위의 내용이 100% 만족스럽지는 않았지만, 아직 극복해야 할 큰 문제가 있는 것 같았습니다.
모바일 퍼스트의 문제점
모바일 퍼스트의 문제는 정의상 후속 미디어 쿼리에서 모바일 퍼스트 스타일을 재정의해야 할 가능성이 높다는 것입니다. 이것은 약간의 안티 패턴처럼 느껴집니다.
그래서 - 나에게 - 대답은 분명했습니다. 미디어 쿼리 구획화에 대한 아이디어를 논리적인 결론으로 가져갑시다. 우리는 또한 모바일 특정 스타일을 고유한 미디어 쿼리로 구획화할 것입니다. 저도 압니다. 이것은 우리가 수년 동안 배운 일반적인 관습에 어긋납니다. "모바일 우선"은 매우 보편적이어서 일반적으로 채용 관리자가 묻는 "기술" 질문 중 하나입니다. 그러니 당연히 어떤 대안도 잘못되어야 하지 않겠습니까? 보통 사람들이 모바일 퍼스트 를 계속해서 내뱉으면서 고개를 흔드는 부분이다.
자, 모바일 퍼스트 도그마를 깨고 모든 스타일을 관련 미디어 쿼리로 분류해 보겠습니다. 이제 우리에게 남은 것은 CSS 선택기에 선언된 순수한 일반 스타일과 관련 화면 크기에만 적용되는 미디어 쿼리에 캡슐화된 다른 모든 장치별 스타일입니다. 이제 Generic First CSS 가 있습니다.
.bio { display: block; width: 100%; @include media('>=0', ' < small') { padding: 20px; margin: 20px 0; } @include media('>=small', ' < medium') { max-width: 400px; margin: 20px auto; } @include media('>=medium', ' < large') { max-width: 600px; padding: 30px; margin: 30px auto; } @include media('>=large', ' < huge') { max-width: 800px; padding: 40px; margin: 40px auto; } @include media('>=huge') { max-width: 1000px; padding: 50px; margin: 50px auto; } }
그림 3. 일반 첫 번째 CSS의 예
예, 약간 더 많은 미디어 쿼리가 있지만 저는 이것이 장점이라고 생각합니다. 이제 모든 개발자가 이 CSS를 보고 미디어를 선택해야 하는 인지적 오버헤드 없이 각각의 모든 화면 크기에 어떤 스타일이 적용되는지 정확하게 볼 수 있습니다. 쿼리 특이성.
이것은 코드 기반이나 미래에 익숙하지 않은 사람들에게 유용할 수 있습니다!
구획화하지 말아야 할 때
여전히 미디어 쿼리 구획화가 부담되는 경우가 있으며, 어떤 경우에는 오래된 >= 미디어 쿼리가 괜찮습니다. 우리가 하려고 하는 것은 속성 덮어쓰기를 피하는 것임을 기억하십시오.
개발 도구 블리스
구획화된 Generic First CSS를 작성할 때 의도하지 않은 주요 결과 중 하나는 개발자 도구 스타일 패널에서 얻을 수 있는 경험입니다. 미디어 쿼리 캐스케이드가 없으면 적용되는 스타일에 대한 더 명확한 개요를 볼 수 있습니다. — 덮어쓴 미디어 쿼리 규칙의 취소선 선언으로 가득 찬 스타일 패널이 없을 것입니다. — 노이즈가 사라졌습니다! 저에게 이것은 Generic First CSS 기술의 가장 큰 이점 중 하나입니다. 그것은 CSS 디버깅 경험에 약간의 온전함을 가져다주며, 이것은 그만한 가치가 있습니다. 나중에 감사합니다.
성능 영향
따라서 이러한 모든 Generic First CSS 이점이 꽤 좋게 들리기 시작했지만 해결해야 한다고 생각하는 마지막 핵심 질문이 하나 있다고 생각합니다. 성능 최적화의 주제입니다. 지금은 아직 확실하지 않지만 완전히 구획화된 미디어 쿼리가 약간의 성능 이점을 가질 수 있다는 것을 짐작할 수 있습니다.
브라우저는 계산된 스타일 계산 이라는 렌더링 작업을 수행합니다. 주어진 순간에 요소에 적용해야 하는 스타일을 계산하는 브라우저 방식입니다. 이 작업은 항상 초기 페이지 로드 시 수행되지만 페이지 콘텐츠가 변경되거나 다른 브라우저 작업이 수행되는 경우에도 수행될 수 있습니다. 프로세스 속도를 높일 수 있는 모든 것은 초기 페이지 로드에 큰 도움이 되며 웹사이트 페이지의 수명 주기에 복합적인 영향을 미칠 수 있습니다.
따라서 일반적인 첫 번째 CSS로 돌아가서: 브라우저가 여러 계단식 미디어 쿼리의 CSS 특수성을 해결해야 하는 것과 관련된 성능 문제가 있습니까?
이에 답하기 위해 저는 속도 이점 또는 실제로 단점을 측정하는 데 사용할 수 있는 테스트 케이스를 고안했습니다.
테스트 케이스
테스트 케이스는 "bio" 블록을 5000번 출력하는 기본 HTML 페이지로 구성되며, 마크업은 각 블록마다 동일하지만 클래스가 약간 다릅니다(숫자 구분자), 이 블록에 대한 CSS도 5000번 출력됩니다 , 클래스 이름만 다를 뿐입니다. 출력된 CSS는 CSS MQPacker라는 도구를 통해 파이프됩니다. 이것은 특정 미디어 쿼리의 모든 개별 인스턴스를 하나로 결합하여 인라인 미디어 쿼리를 많이 사용하는 CSS의 파일 크기를 크게 줄이는 데 도움이 됩니다. 가장 현대적인 CSS 코드베이스 — 테스트 프로젝트 package.json에서 npm 작업을 통해 독립 실행형 cli 도구로 사용했습니다. postcss 플러그인으로 사용할 수도 있습니다. 이는 훌륭하고 편리합니다!
첫 번째 테스트 케이스는 모바일 우선 캐스케이딩 미디어 쿼리 예제이고, 두 번째 테스트 케이스는 CSS의 일반적인 첫 번째 구획화된 변형입니다. 이러한 경우에 대한 CSS는 약간 장황하고 아마도 훨씬 더 간결한 용어로 작성될 수 있지만 실제로는 인수를 테스트하기 위한 대략적인 예일 뿐입니다.
테스트는 데스크톱 Google Chrome v70의 각 CSS 변형에 대해 20번 실행되었으며, 방대한 데이터 세트는 아니지만 성능 이득/손실에 대한 대략적인 아이디어를 제공하기에 충분했습니다.
내가 사용하기로 선택한 테스트 메트릭은 다음과 같습니다.
- 전체 페이지 로드 시간
<head>의 시작 부분과 <body>의 맨 끝에 있는 Performance API 마커를 사용하여 페이지 로드 시간을 확인하는 기본 메트릭 - 스타일 다시 계산
개발 도구 성능 창 내에서 발생한 시간입니다. - 전체 페이지 렌더링
개발 도구 성능 창 내에서 발생한 시간입니다.
결과 테이블(모든 시간(밀리초))
모바일 퍼스트 | 일반 우선 | ||||||
---|---|---|---|---|---|---|---|
로드 시간 | 스타일 계산 | 총 렌더링 시간 | 로드 시간 | 스타일 계산 | 총 렌더링 시간 | ||
1135 | 565.7 | 1953년 | 1196 | 536.9 | 2012년 | ||
1176 | 563.5 | 1936년 | 1116 | 506.9 | 1929년 | ||
1118 | 563.1 | 1863년 | 1148 | 514.4 | 1853년 | ||
1174 | 568.3 | 1929년 | 1124 | 507.1 | 1868년 | ||
1204 | 577.2 | 1924년 | 1115 | 518.4 | 1854년 | ||
1155 | 554.7 | 1991년 | 1177 | 540.8 | 1905년 | ||
1112 | 554.5 | 1912년 | 1111 | 504.3 | 1886년 | ||
1110 | 557.9 | 1854년 | 1104 | 505.3 | 1954년 | ||
1106 | 544.5 | 1895년 | 1148 | 525.4 | 1881년 | ||
1162 | 559.8 | 1920년 | 1095 | 508.9 | 1941년 | ||
1146 | 545.9 | 1897년 | 1115 | 504.4 | 1968년 | ||
1168 | 566.3 | 1882년 | 1112 | 519.8 | 1861년 | ||
1105 | 542.7 | 1978년 | 1121 | 515.7 | 1905년 | ||
1123 | 566.6 | 1970년 | 1090 | 510.7 | 1820년 | ||
1106 | 514.5 | 1956년 | 1127 | 515.2 | 1986년 | ||
1135 | 575.7 | 1869년 | 1130 | 504.2 | 1882년 | ||
1164 | 545.6 | 2450 | 1169 | 525.6 | 1934년 | ||
1144 | 565 | 1894년 | 1092 | 516 | 1822년 | ||
1115 | 554.5 | 1955년 | 1091 | 508.9 | 1986년 | ||
1133 | 554.8 | 2572 | 1001 | 504.5 | 1812년 | ||
AVG | 1139.55 | 557.04 | 1980년 | 1119.1 | 514.67 | 1903.15 |
그림 6. 모바일 퍼스트 대 일반 퍼스트 CSS의 주요 로드/렌더 메트릭을 측정하는 20개의 테스트 실행.
내가 인정하는 작은 데이터 세트에서, 내 초기 의심이 정확할 수 있는 것처럼 보입니다. 평균적으로 스타일 재계산 작업에 걸리는 시간은 42ms로 7.6% 빨라져 전체 렌더링 시간도 감소합니다. 그 차이는 놀랍지는 않지만 개선된 것입니다. 데이터 세트가 100% 결정적일 만큼 크지 않고 테스트 사례가 약간 비현실적이라고 생각하지만 성능 저하를 보지 않아 매우 기쁩니다.
저는 모바일 퍼스트 방식으로 작성된 실제 기존 코드베이스에 일반적인 퍼스트 방법론을 적용하는 데 매우 관심이 있습니다.
그리고 더 광범위한 반복 세트에서 이 테스트를 자동화하는 방법에 대한 제안이 있는 사람이 있으면 댓글로 알려주세요! 이 작업을 수행할 수 있는 도구가 있어야 한다고 생각합니다.
결론
이 새로운 개발 방법론의 이점을 요약하자면...
- 두 번째 추측 없이 의도한 대로 정확히 수행하는 CSS
- 자체 문서화 미디어 쿼리;
- 더 나은 개발 도구 경험;
- 더 빠르게 렌더링되는 페이지.
이 스타일의 CSS 작성을 지지하는 사람은 나뿐만이 아니라고 생각합니다. 일반적인 첫 번째 사고 방식을 이미 채택했다면 만세! 하지만 그렇지 않다면 그것이 가져다주는 이점을 정말 좋아할 것이라고 생각합니다. 저는 개인적으로 깔끔한 개발 도구 경험에서 큰 이점을 얻었으며, 이는 그 자체로 많은 개발자에게 큰 긍정적인 영향을 줄 것입니다. 미디어 쿼리를 작성하는 이 방법의 자체 문서화 특성은 자신과 더 넓은 팀(있는 경우)에도 이점이 있습니다. 그리고 마지막으로, 이러한 이점은 성능 측면에서 비용이 들지 않으며 실제로 속도가 약간 향상되는 것으로 나타났습니다!
마지막 단어
모든 개발 방법론과 마찬가지로 모든 사람에게 해당되는 것은 아니지만 저는 Generic First CSS에 아주 자연스럽게 빠져 들었습니다. 이제 모바일 우선의 모든 이점을 제공하는 귀중한 작업 방식으로 보고 있습니다. 프론트엔드 개발이라는 힘든 일을 조금 더 쉽게.
자원
테스트 케이스 리포지토리
테스트 케이스를 시작하고 직접 시도해 보고 싶다면 GitHub에서 찾을 수 있습니다. 다른 사람들의 보고서를 보고 싶습니다.
도구
- CSS MQPacker
- 미디어 포함