Flexbox 및 Sass Grid 튜토리얼: 반응형 디자인을 간소화하는 방법
게시 됨: 2022-03-11최근에 나는 나만의 그리드 시스템을 만들어야 한다는 도전을 받았고, 바퀴를 재발명하는 것은 학습 경험으로 항상 유용하기 때문에 선택했습니다. 흥미로운 도전이 될 줄 알았지만 생각보다 쉬워서 놀랐습니다!
이 실험에서는 Flexbox 레이아웃과 미친 해킹 없이 레이아웃을 우아하게 구현하는 방법을 살펴보겠습니다. 또한 Sass에 익숙하지 않다면 Sass가 어떻게 작동하는지 살펴보고 편리한 Sass 유틸리티를 사용할 것입니다. Bootstrap의 일부인 CSS 그리드와 같은 CSS 그리드에 대해 새로운 것을 배울 수도 있습니다.
Sass와 Flexbox에 대한 아주 짧은 소개
Sass는 기본적으로 CSS의 일부 단점을 피할 수 있는 도구이며 CSS로 해석되는 스크립팅 언어입니다. 이미 CSS 스타일을 작성하고 있는 경우 구문이 매우 친숙해 보이지만 도구 상자에 변수, 재사용성을 위한 믹스인, if, for, each 및 while 지시문이 포함되어 있습니다. Sass의 가장 편리한 점 중 하나는 모든 유효한 CSS 코드가 유효한 Sass이므로 코드 기반을 점진적으로 변형할 수 있다는 것입니다.
for 루프의 간단한 예:
@for $i from 1 through 3 { .a-numbered-class-#{$i} { width: (20 * $i) * 1px; } } 이 간단한 루프는 1에서 3까지 반복하고 클래스를 만듭니다. 반복의 인덱스는 $i 에 쉽게 저장됩니다. 우리는 또한 수학을 할 수 있고 매번 다른 너비 .a-numbered-class-X 를 세 번 인쇄할 수 있습니다. 이 코드는 다음을 출력합니다.
.a-numbered-class-1 { width: 20px; } .a-numbered-class-2 { width: 40px; } .a-numbered-class-3 { width: 60px; }보시다시피 CSS에서 수행해야 하는 많은 작업을 추상화할 수 있습니다. CSS에서는 수동으로 복사하여 붙여넣고 수정해야 합니다. 이는 분명히 오류가 발생하기 쉽고 덜 우아합니다. 아직 시도하지 않았다면 더 이상 시간을 낭비하지 마십시오!
Flexbox는 요소를 동적으로 배치하고 배포하는 CSS3 레이아웃 시스템인 Flexible Box의 약자입니다. 최소한의 노력으로 유연한 레이아웃을 허용하는 매우 강력한 도구입니다. Flexbox를 배우는 방법에 대한 자세한 내용은 Chris Coyier의 Flexbox에 대한 전체 가이드를 확인하세요.
그리드
그리드 자체로 이동하여 기본 요소부터 시작하겠습니다. 그것들은 Bootstrap의 그리드 요소인 Containers, Rows, Columns에서 영감을 받을 것입니다. 각각 전자 안에 포함되어 있습니다.
우리는 클래스 이름에 BEM 명명 규칙을 사용할 것입니다. BEM 규칙은 사용하기가 매우 간단하며 요소 및 해당 컨텍스트에 대한 많은 정보를 추가합니다. 간단히 말해서 다음이 있습니다.
- "그 자체로 의미 있는 독립 실행형 엔터티를 캡슐화"하는 블록 :
.block. - 블록 이름, 두 개의 밑줄 및 요소 로 표시되는 "블록의 일부이며 독립형 의미가 없는" 요소:
.block__elem - "블록 또는 요소에 대한 플래그"와 같은 수정 자는 두 개의 대시로 표시됩니다.
.block .block--mod.
컨테이너
이것은 그리드의 가장 바깥쪽 요소이며 행 요소를 포함합니다. 컨테이너에는 .container 및 .container--fluid 의 두 가지 유형이 있습니다.
.container 의 동작은 특정 지점 아래 너비의 100%로 정의되며 그 위에 최대 고정 너비가 있고 왼쪽과 오른쪽 여백이 동일합니다.
$grid__bp-md: 768; .container { max-width: $grid__bp-md * 1px; margin: 0 auto; }"출력" 창을 확장 및 축소하여 여기에서 재생합니다.
항상 너비가 100%인 유체 컨테이너의 경우 수정자로 해당 속성을 재정의합니다.
&--fluid { margin: 0; max-width: 100%; }여기에서 함께 플레이하세요.
그것은 쉽다! 이제 두 컨테이너가 모두 구현되었습니다. 다음 요소로 넘어갑시다.
행
행은 콘텐츠의 수평 구성자가 됩니다.
Flexbox를 사용하여 행의 자식 요소를 배치하고 오버플로하지 않도록 랩을 만들고 행 내부에 100% 너비를 제공합니다(나중에 중첩할 수 있도록).
&__row { display: flex; flex-wrap: wrap; width: 100%; }이것은 자식 요소를 나란히 배치하고 너비의 합이 자체보다 큰 경우 새 줄로 줄 바꿈합니다. 이제 div를 추가하기만 하면 됩니다. 그러면 다음과 같이 보일 것입니다.
"출력" 창을 확장 및 축소하여 여기에서 재생합니다.
상황이 형성되기 시작했지만 이것은 아직 CSS 그리드가 아닙니다. 누락되었습니다…
열
열은 사이트의 콘텐츠가 있는 곳입니다. 그들은 행이 분할된 부분과 차지하는 부분을 정의합니다. 우리는 열두 열 레이아웃을 할 것입니다. 이것은 행을 하나 또는 최대 12개의 부분으로 나눌 수 있음을 의미합니다.
시작하려면 몇 가지 기본 수학. 하나의 열을 가지려면 너비가 100%여야 합니다. 12개의 열이 필요한 경우. 그런 다음 각각은 너비의 8.333...% 또는 100/12를 차지해야 합니다.
Flexbox를 사용하여 이러한 방식으로 콘텐츠를 배포하려면 flex-basis 를 사용할 수 있습니다.
4개의 열로 나누기 위해 이제 다음과 같이 추가합니다.
flex-basis: (100 / 4 ) * 1%;이런 식으로 요소가 너비의 25% 또는 원하는 비율을 차지하도록 할 수 있습니다.
여기에서 함께 플레이하세요.
좀 더 역동적으로 만들어 봅시다. 이것이 가능한 클래스를 반영하기를 원하기 때문에 .col-1 을 호출하겠습니다. 열 div의 클래스는 너비의 8.333%를 가질 것입니다. 열 div는 새 줄로 래핑해야 하기 전에 12개가 맞아야 하기 때문입니다. 백분율은 100%를 차지하는 .col-12 까지 계속 증가합니다.
$grid__cols: 12; @for $i from 1 through $grid__cols { .col-#{$i} { flex-basis: (100 / ($grid__cols / $i) ) * 1%; } } 무슨 일이 일어나고 있는지 명확히 하기 위해 너비를 4등분으로 나누고 싶다고 가정해 보겠습니다. .col-3 은 12에 4번 맞기 때문에 필요합니다. 즉, .col-3 은 25% 플렉스 기반을 가져야 합니다.
100 / ($grid__cols / $i) 100 / (12 / 3) = 25이것은 이미 그리드처럼 보이기 시작했습니다!
여기에서 함께 플레이하세요.
화면 너비 종속 열
이제 모바일에서는 특정 너비를 갖지만 태블릿에서는 다른 너비를 갖는 요소를 가질 수 있기를 원합니다. 창의 너비에 따라 특정 중단점을 사용합니다. 우리의 UI는 이러한 중단점에 반응하고 다양한 장치의 화면 크기에 맞는 이상적인 레이아웃에 적응합니다. 중단점의 이름은 small(sm), medium(md) 등으로 크기별로 지정합니다. .col-sm-12 는 sm 중단점까지 최소한 12열을 차지하는 요소입니다.
.col-* class .col-sm-* sm-* 의 이름을 바꾸겠습니다. 그리드는 모바일 우선이므로 모든 화면 크기에 해당 속성을 적용합니다. 더 큰 화면에서 다르게 동작해야 하는 경우 .col-md-* 클래스를 추가합니다.

.col-sm-12 및 .col-md-4 가 있는 요소를 상상해 보세요. 예상되는 동작은 중단점 "md"(중간) 아래에서 너비가 100%이고 그 이상에서는 33.333%가 되는 것입니다. 모바일에서는 요소를 옆이 아닌 맨 위에 쌓아야 할 수 있기 때문에 매우 흔한 일입니다. 너비가 훨씬 더 제한적일 때 서로.
이를 위해 중단점에 미디어 쿼리(특정 너비 또는 특정 장치에서만 실행되는 코드를 포함하는 표현식)를 추가하고 sm 에 대해 이전에 했던 것처럼 md 열을 생성해야 합니다.
@media screen and (min-width: $grid__bp-md * 1px) { @for $i from 1 through $grid__cols { &__col-md-#{$i} { flex-basis: (100 / ($grid__cols / $i) ) * 1%; } } }여기에서 함께 플레이하세요.
그것은 이미 유용한 것에 가까워지고 있습니다. 그것은 꽤 WET입니다(알았습니까? DRY가 아닙니다...), 그래서 더 추상적으로 만들겠습니다.
보았듯이 각 중단점에 대한 미디어 쿼리가 필요하므로 미디어 쿼리를 동적으로 생성하는 중단점을 수신하는 믹스인을 생성해 보겠습니다. 다음과 같이 보일 수 있습니다.
@mixin create-mq($breakpoint) { @if($breakpoint == 0) { @content; } @else { @media screen and (min-width: $breakpoint *1px) { @content; } } } 이제 create-col-classes 라는 믹스인에서 __col 클래스를 생성하기 위해 준비한 것을 래핑하고 create-mq mixin을 사용하겠습니다.
@mixin create-col-classes($modifier, $grid__cols, $breakpoint) { @include create-mq($breakpoint) { @for $i from 1 through $grid__cols { &__col#{$modifier}-#{$i} { flex-basis: (100 / ($grid__cols / $i) ) * 1%; } } } }그리고 그게 다야. 이를 사용하기 위해 이제 Sass 맵에서 중단점을 정의하고 반복합니다.
$map-grid-props: ('-sm': 0, '-md': $grid__bp-md, '-lg': $grid__bp-lg); @each $modifier , $breakpoint in $map-grid-props { @include create-col-classes($modifier, $grid__cols, $breakpoint); } 그리드 시스템은 기본적으로 완료되었습니다! 기본값이 될 .container__col-sm-* 클래스를 정의했으며 container__col-md-* 및 container__col-lg-* *를 사용하여 더 큰 화면에서 동작을 수정할 수 있습니다.
행을 중첩할 수도 있습니다! 여기에서 함께 플레이하세요.
이것에 대한 좋은 점은 이제 Bootstrap v4와 동일한 중단점을 갖기를 원한다면 다음과 같이 하면 된다는 것입니다.
$grid__bp-sm: 576; $grid__bp-md: 768; $grid__bp-lg: 992; $grid__bp-xl: 1200; $map-grid-props: ( '': 0, '-sm': $grid__bp-sm, '-md': $grid__bp-md, '-lg': $grid__bp-lg, '-xl': $grid__bp-xl );그리고 그게 다야! 여기에서 함께 플레이하세요.
Bootstrap이 처음에 논의한 것보다 더 완전한 모바일 우선 접근 방식을 취하는 방법에 주목하십시오. 가장 작은 창 크기에는 sm 또는 md 와 같은 접미사가 없습니다. 그 이유는 .container__col-X 에 해당하는 클래스가 0에서 576px의 창 너비에서만 적용되지 않기 때문입니다. 명시적으로 덮어쓰지 않으면 모든 창 크기에서 해당 개수의 열이 됩니다. 그렇지 않으면 .container__col-sm-Y 클래스를 추가하여 sm 중단점 사이의 Y 열 너비로 만들 수 있습니다.
오프셋
오프셋은 이전 열과 관련하여 남은 여백을 추가합니다. .container__col-offset-4 는 모든 화면 크기에서 margin-left: 33.333% 를 추가합니다. .container__col-md-offset-4 는 동일하지만 md 중단점 위에 있습니다.
구현은 이제 간단합니다. 클래스를 생성하는 동일한 루프에 -offset 속성을 추가하지만 flex-bases 대신 margin-left 속성을 작성합니다. 더 큰 화면에서 여백을 지우고 싶을 수 있으므로 -offset-0 에 대해서도 추가 작업을 수행해야 합니다.
@mixin create-col-classes($modifier, $grid-cols, $breakpoint) { @include create-mq($breakpoint) { &__col#{$modifier}-offset-0 { margin-left: 0; } @for $i from 1 through $grid-cols { &__col#{$modifier}-#{$i} { flex-basis: (100 / ($grid-cols / $i) ) * 1%; } &__col#{$modifier}-offset-#{$i} { margin-left: (100 / ($grid-cols / $i) ) * 1%; } } } }이제 완전히 기능적인 오프셋이 있습니다! 여기에서 함께 플레이하세요.
디스플레이 가능성
우리는 때때로 특정 지점 아래 또는 위에 요소를 표시/숨기기를 원합니다. 이를 위해 Bootstrap v4와 같은 클래스를 사용할 수 있습니다.
예를 들어, .hidden-md-up 클래스는 md 중단점 위쪽에서 이 클래스를 가진 모든 요소를 숨깁니다. 반대로 .hidden-md-down 은 중단점에서 숨깁니다.
이에 대한 코드는 다시 간단합니다. 중단점을 반복하고 for each 중단점에 대해 .hidden-* 클래스를 생성하기만 하면 됩니다. 우리는 create-mq 클래스를 조금 더 추상적으로 수정했습니다.
@each $modifier , $breakpoint in $map-grid-props { @if($modifier == '') { $modifier: '-xs'; } @include create-mq($breakpoint - 1, 'max') { .hidden#{$modifier}-down { display: none !important; } } @include create-mq($breakpoint, 'min') { .hidden#{$modifier}-up { display: none !important; } } } 참고로 이것은 !important 의 몇 안 되는 좋은 용도 중 하나가 아닙니까? 요소는 display: block 규칙을 사용하여 임의로 더 큰 특이성을 가질 수 있지만 여전히 중단점 아래 또는 위에 숨기고 싶습니다. 이 접근 방식에 동의하지 않는 경우 댓글로 알려주세요!
이제 끝입니다. 이제 표시 가능성 시스템이 있습니다.
여기에서 함께 플레이하세요.
결론
이 "프레임워크"는 프로덕션 준비가 되지 않았지만 Flexbox 레이아웃이 얼마나 강력하고 Sass가 얼마나 편리한지를 보여줍니다. 몇 줄의 코드로 CSS 프레임워크/그리드의 핵심 기능을 구현했습니다.
또한 거의 모든 소프트웨어의 기본 버전이 매우 쉽게 구현될 수 있다는 교훈이 되기를 바랍니다. 현실 세계의 구체적인 문제들이 더해지기 시작하고 그것을 어렵게 만드는 것입니다.
이슈나 풀 리퀘스트를 제출할 수 있는 GitHub 리포지토리를 만들었습니다.
구현되었으면 하는 기능은 무엇입니까? 구현이 단순화되거나 더 우아해질 수 있습니까?
아래 의견에 대한 귀하의 의견을 자유롭게 알려주십시오.
