Flexbox에서의 width속성 알아보기
Flexbox로 만드는 사이드바 레이아웃 안정성 높이기
Flexbox로 만드는 그리드의 한계 -> 클래스 기반, 12단 그리드 시스템 구축
미디어쿼리를 이용한 반응형웹
▲ flex items 부가설명
flex items의 width의 개념은
width:300px 일때 / flex-basis: auto -> 300px / min-width: auto -> 300px 의 특징을 가지고 있다.
만약 width:300px 일 때와 basis값이 200px 일 경우에는
basis 값이 auto 였으면 300px을 받아오지만 basis값이 우선적 200px이 적용된다.
만약 width 값을 적용하지 않고 basis값 만 적용 할 경우 내부 컨텐츠 크기 만큼 잡힌다.
◆ (day09/mini/sidebar)
playground 클래스에 display:flex 지정하고 컨텐츠내용을 추가하면
<div class="playground">
<div class="contents">Contents Contents Contents Contents Contents Contents Contents</div>
<div class="contents">Contents Contents Contents Contents Contents</div>
</div>
더 많은 컨텐츠를 담고 있는 요소가 더 크다 보여지는 그대로
줄바꿈이 되더라도 내부의 텍스트 양만큼 flex items 크기를 할당해준다.
하지만 레이아웃을 먼저 잡지않고 내부 컨텐츠를 넣으면 안된다
내부의 컨텐츠 양이 많이질수록 틀어지기 때문에 항상 레이아웃 먼저 구성해야한다.
body {
background-color: brown;
}
.playground {
border: 10px solid maroon;
width: 980px;
margin: 0 auto;
border-radius: 30px;
background-color: skyblue;
padding: 10px;
display: flex;
}
.sidebar,
.contents {
background-color: mediumseagreen;
color: lime;
font-size: 40px;
border: 6px solid green;
border-radius: 10px;
min-height:400px
}
.sideber
.contents {
}
사이드바는 너비 고정 값을 지정하고 컨텐츠는 flex-grow 1 값을 지정해준다. 붙어있으므로 gap으로 띄워준다.
.playground {
border: 10px solid maroon;
width: 980px;
margin: 0 auto;
border-radius: 30px;
background-color: skyblue;
padding: 10px;
display: flex;
gap:10px
}
.sideber{
width: 180px;
}
.contents {
flex-grow: 1;
}
컨텐츠를 넣어보면 내부의 컨텐츠가 많아지므로 사이즈가 맞춰져 커지고 사이드바는 고정값이지만 줄어든다.
만약 그럼 이 때는 min-width: auto;가 계산되는 방식이 shrink로 인해 줄어든 width값을 따라간다.
사이드바 180px이 유지되게 하려면 수축 되지 않게 shrink 값을 0으로 지정해준다.
.sidebar{
width: 180px;
min-width: 180px;
/* flex-shrink: 0; */
}
.contents {
flex-grow: 1;
}
두번째는 사이드바에 크기가 작아지지 않게 min-width값을 180px 지정해도 된다.
세 번째 방법으로는 컨텐츠에 basis 값을 0으로 준다
사이드바가 컨텐츠에게 계속 밀리다보니 shrink를 0으로 해주거나 min-width를 0으로 해주었지만
내부 컨텐츠 양이 커지다보니 사실은 컨텐츠 클래스에 초점을 맞춰줘야한다.
.sidebar{
width: 180px;
}
.contents {
flex-grow: 1;
flex-basis: 0;
}
그렇다면 컨텐츠상자 안에 텍스트가 많아질 때 줄 바꿈이 되기는 하지만
어쨌든 너비는 콘텐츠 양에 대응해서 넓어지는것도 flex-basis: auto 이라는 것도 알 수가 있다.
하지만 그렇다고 해서 완벽한 레이아웃이 된 것이 아니다.
사이드바가 고정값을 지정되어있기에 넘치지는 않지만 내부 컨텐츠가 넘칠경우 문제가 생긴다.
컨텐츠는 가변이므로 min-width를 0으로 지정 해 주면 되는데
레이아웃은 부모 관점에서 안정성을 확보 해야 하고
내부 컨텐츠는 안정성 확보된 레이아웃 내에서 자연스럽게 배치 되는 것이므로 최소 너비를 0 으로 지정 해 줘야 한다.
레이아웃 잡는데 min-width가 상당히 중요하다.
▼3줄요약
flex-grow:1 = 가용 공간을 가득 채운다. flex-basis:0 = 내부 콘텐츠 크기+ grow가 아닌 grow로만 사이즈가 결정 될 수 있도록 한다. min-width:0 = 내부 콘텐츠가 부모의 너비에 영향을 끼치지 않게 끔 처리한다. |
See the Pen Flex Items와 min-width: 0 지정하기 by VEAMCAMP (@veamcamp) on CodePen.
■ veamflex 내부 레이아웃 콘텐츠 넣기
▼ 사이드바 만들기
위에서 배운 토대로 미래지향적으로 container-main 클래스에 basis와 min-width 추가해준다
.container-main{
box-shadow: inset 0 0 30px dodgerblue;
flex-grow: 1;
flex-basis: 0;
min-width: 0;
}
사이드 바는 고정이므로 basis값보단 width 168px 값을 지정해준다.
.container-sidebar {
box-shadow: inset 0 0 30px orangered;
/* flex-basis: 168px; */
width: 168px;
height: 340px;
}
사이드 바의 내부 콘텐츠를 추가해보자면
<div class="container-sidebar">
<aside>
<h3>Genre</h3>
<ul>
<li>
<h3>Action & Adventure</h3>
<ul>
<li><a href=""></a>Adventure</li>
<li><a href=""></a>Action Thrillers</li>
<li><a href=""></a>Superhero Movies</li>
</ul>
</li>
<li>
<h3>Dramas</h3>
<ul>
<li><a href=""></a>Crime Dramas</li>
<li><a href=""></a>Teen Dramas</li>
<li><a href=""></a>Romantic Dramas</li>
</ul>
</li>
</ul>
</aside>
</div>
</div>
aside는 보통 로컬 메뉴와 글로벌 메뉴로 사용한다.
▼잘못 작성하기 쉬운 마크업 p요소 내부의 div 불가 h1 ~ h6요소 내부의 div 불가 ol, ul요소 직계 자식은 li만 가능 클릭 가능한 요소 내부의 클릭 가능한 요소 불가. (a, button, label 등) 예시) a요소 내부의 a요소 불가 ▼의외로 가능한 마크업 a요소 내부의 div 구성 가능 단 CSS 측면에서 a요소에게 display: block li: 종료 태그없이 사용 가능하지만 추천하지 않음. |
<ul,li,h1,h3, a요소 초기화 진행>
body, p ul{
margin: unset;
padding: unset;
}
h1, h2{
margin: unset;
font-size: unset;
font-weight: unset;
}
li {
list-style-type: none;
}
a{
color: unset; /*a 요소 클릭하면 보라색 되는거 없앰*/
text-decoration: unset;
}
aside와 변경되어야할 각 요소들에게 클래스를 지정해준다.
<div class="container-sidebar">
<aside class="category">
<h2>Genre</h2>
<ul class="category-list">
<li class="category-item">
<h3>Action & Adeventure</h3>
<ul class="category-sub">
<li><a href="">Adventures</a></li>
<li><a href="">Action Thrillers</a></li>
<li><a href="">Superhero Movies</a></li>
</ul>
</li>
<li class="category-item">
<h3>Dramas</h3>
<ul class="category-sub">
<li><a href="">Crime Dramas</a></li>
<li><a href="">Teen Dramas</a></li>
<li><a href="">Romantic Dramas</a></li>
</ul>
</li>
</ul>
</aside>
</div>
.container-sidebar {
box-shadow: inset 0 0 4px orangered;
width: 168px;
}
.category h2 {
margin-bottom: 12px;
}
.category-item {
border-top: 1px solid #FA8073;
background-color: #111111;
}
.category-item h3 {
color: #FA8073;
padding: 8px 10px;
font-size: 14px;
}
.category-sub {
font-size: 12px;
margin-left: 20px;
padding: 10px 0;
}
.category-sub li {
padding: 6px 0;
}
.category-sub li + li {
border-top: 1px solid #333;
}
▼ 메뉴버튼 만들기
마크업으로보단 가상요소 클래스를 사용한다.
가상요소는 디스플레이 속성이 인라인이므로 해당요소의 카테고리 h2의 자식요소로 추가된것.
.category h2::before{
content: 'before';
}
그렇다면 h2에다가 flex와 중앙 정렬을 적용하고 gap을 써서 간격을 벌린다.
.category h2 {
margin-bottom: 12px;
display: flex;
align-items: center;
gap: 10px;
}
.category h2::before{
background-color: aqua;
content: 'before';
width: 30px;
height: 30px;
}
하지만 위에서 배웠다 시피 해당 요소에 콘텐츠가 늘어나면 작아지면서 변형이 생기기때문에
.category h2::before{
background-color: aqua;
content: 'before';
width: 30px;
height: 30px;
flex-shrink: 0;
}
가상요소에 felx-shrink:0으로 지정한다.
번외 - 이미지 스프라이트 기법
또한 img srcset 라는 것도 있는데 이미지의 여러가지 상태를 묶어서 표현한다.
미디어 조건에 따라서 불러오는 이미지가 다르다. 이러한 기법으로도 이미지 성능을 올릴 수 있다.
▼ 메인 만들기
먼저 레이아웃 만드는 거에 초점을 맞추기위해 레이아웃과 컴포넌트를 구분한다.
(l_row l_col 은 레이아웃 역할, card는 컴포넌트 역할로 구분)
<div class="container-main">
<ul class="l_row">
<li class="l_col ">
<section class="card">A</section>
</li>
<li class="l_col">
<section class="card">B</section>
</li>
<li class="l_col">
<section class="card">C</section>
</li>
</ul>
</div>
해당 ul와 li들은 반응형 구조
컨텐츠 크기만큼 만들기위해 row에 display flex 적용하고 사이간격을 늘린다.
.l_row{
background-color: yellow;
display: flex;
}
.L_col{
background-color: orange;
}
.card{
background-color: darkcyan;
}
사이즈를 꽉 차게 col에 flex-grow를 적용한다.
.l_row{
background-color: yellow;
display: flex;
row-gap: 20px;
}
.l_col{
background-color: orange;
flex-grow:1;
flex-basis: 0;
min-width: 0;
}
컨텐츠에 들어가는것 크기나 길이에 관계없이 레이아웃이 잘 적용되게 근본순서인 basis와 min-with를 적용해준다
완성이미지를 보면 li가 총 6개이다 html에 li를 6개로 추가하면 줄바꿈이 되지않는걸 확인할 수있다
그렇기에 row에 flex-wrap:wrap를 추가해준다.
안되는 이유는 basis가 0이기에 어느 줄에 바꿀지 정보가 없기때문에 grow를 뺴고 basis를 늘려준다.
.l_col{
background-color: orange;
/* flex-grow:1; */
flex-basis: 150px;
min-width: 200px;
}
150px 기준으로 늘어나기에 basis를 줄바꿈 기준으로 보면된다.
허나 위에서 배웠다시피 basis 150px 대신 그냥 width 150px로 하면된다.
.l_col{
background-color: orange;
/* flex-grow:1; */
/* flex-basis: 150px; */
width: 150px;
}
col에 grow를 다시 살려준다
.l_col{
background-color: orange;
flex-grow:1;
/* flex-basis: 150px; */
width: 200px;
}
근데 화면을 늘리면 이상하게 배치가 되어있는걸 볼수있다.
이결 해결하기위해 다시 grow를 빼주고 3단 그리드를 유지시켜야 하므로 width를 %값으로 넣어준다
.l_row{
background-color: yellow;
display: flex;
row-gap: 20px;
flex-wrap: wrap;
}
.l_col{
background-color: orange;
/* flex-grow:1; */
/* flex-basis: 150px; */
width: calc(100%/3); /*33.333333%*/
padding:0 10px;
box-sizing: border-box;
/*(column-gap의 갯수 * column-gap 수치) / coloumn 개수*/
}
박스사이징을 이용하여 width+padding 값 적용한 줄에 3개가 온전히 올 수 있도록 구성해준다.
row에 좌우 네거티브 마진을 적용하여 wrapper에 정렬 맞추고 card 패딩을 조금 늘려준다.
.l_row{
background-color: yellow;
display: flex;
row-gap: 20px;
flex-wrap: wrap;
margin: 0 -10px;
}
레이아웃을 좀 더 유연하게 하자면 우선 li에 따로 클래스를 하나더 지정해준다음에 주어지진 코드를 추가해준다.
<ul class="l_row">
<li class="l_col l_col_4_12">
<section class="card">A</section>
</li>
<li class="l_col l_col_4_12">
<section class="card">B</section>
</li>
<li class="l_col l_col_4_12">
<section class="card">B</section>
</li>
<li class="l_col l_col_4_12">
<section class="card">B</section>
</li>
<li class="l_col l_col_4_12">
<section class="card">A</section>
</li>
<li class="l_col l_col_4_12">
<section class="card">B</section>
</li>
</ul>
.l_col_12_12 { width: 100%; }
.l_col_11_12 { width: 91.66666667%; }
.l_col_10_12 { width: 83.33333333%; }
.l_col_9_12 { width: 75%; }
.l_col_8_12 { width: 66.66666667%; }
.l_col_7_12 { width: 58.33333333%; }
.l_col_6_12 { width: 50%; }
.l_col_5_12 { width: 41.66666667%; }
.l_col_4_12 { width: 33.33333333%; }
.l_col_3_12 { width: 25%; }
.l_col_2_12 { width: 16.66666667%; }
.l_col_1_12 { width: 8.33333333%; }
해당 그리드가 3단으로 960보다 창크기가 작아졌을때 2단,1단씩 줄어들게 하고싶다할때
@media 미디어 쿼리를 사용하여 col의 너비를 50%로 지정해준다.
@media (max-width: 960px) {
.l_col {
width: 50%;
}
}
하지만 이방법 보단 유연하게 레이아웃을 변경하기위해 그리드 코드를 가져온다 https://d.pr/ru2
또한 li에 클래스를 추가하여 그리드 스타일 자체를 좀더 쉽게 변경 가능하다.
<ul class="l_row">
<li class="l_col l_col_4_12 l_col_tabel_6_12">
<section class="card">A</section>
</li>
<li class="l_col l_col_4_12 l_col_table_6_12">
<section class="card">B</section>
</li>
<li class="l_col l_col_4_12 l_col_table_6_12">
<section class="card">B</section>
</li>
<li class="l_col l_col_4_12 l_col_table_6_12">
<section class="card">B</section>
</li>
<li class="l_col l_col_4_12 l_col_table_6_12">
<section class="card">A</section>
</li>
<li class="l_col l_col_4_12 l_col_table_6_12">
<section class="card">B</section>
</li>
<li class="l_col l_col_4_12 l_col_table_6_12">
<section class="card">B</section>
</li>
</ul>
@media (max-width:960px) {
.l_col_table_12_12 { width: 100%; }
.l_col_table_11_12 { width: 91.66666667%; }
.l_col_table_10_12 { width: 83.33333333%; }
.l_col_table_9_12 { width: 75%; }
.l_col_table_8_12 { width: 66.66666667%; }
.l_col_table_7_12 { width: 58.33333333%; }
.l_col_table_6_12 { width: 50%; }
.l_col_table_5_12 { width: 41.66666667%; }
.l_col_table_4_12 { width: 33.33333333%; }
.l_col_table_3_12 { width: 25%; }
.l_col_table_2_12 { width: 16.66666667%; }
.l_col_table_1_12 { width: 8.33333333%; }
}
모바일 버전도 따로 작업 할 수있다 최대 너비를 480px까지 지정하면 된다.
/*모바일도 따로 추가 해서 작업가능*/
@media (max-width:480px) {
.l_col_mobile_12_12 { width: 100%; }
.l_col_mobile_11_12 { width: 91.66666667%; }
.l_col_mobile_10_12 { width: 83.33333333%; }
.l_col_mobile_9_12 { width: 75%; }
.l_col_mobile_8_12 { width: 66.66666667%; }
.l_col_mobile_7_12 { width: 58.33333333%; }
.l_col_mobile_6_12 { width: 50%; }
.l_col_mobile_5_12 { width: 41.66666667%; }
.l_col_mobile_4_12 { width: 33.33333333%; }
.l_col_mobile_3_12 { width: 25%; }
.l_col_mobile_2_12 { width: 16.66666667%; }
.l_col_mobile_1_12 { width: 8.33333333%; }
}
결론적으로 반응형 웹을 만들어본 것이다.
이제 카드내부를 추가해보자면
3단으로 구성되어있으며 이미지 img와 내용 p와 버튼으로 구분할 수있다.
이제 각 섹션 카드에 클래스를 추가한다.
<section class="card">
<img src="" alt="" class="card-cover">
<div class="card-contents"></div>
<div class="card-controls"></div>
</section>
이미지를 관리하려면 width %로 적용한다.
.card-cover{
width: 100%;
}
.card-contents{
box-shadow: inset 0 0 10px red;
padding: 20px;
}
.card-controls{
box-shadow: inset 0 0 10px blue;
padding: 10px;
}
내용을 넣기위해 콘텐츠 클래스에 h1과 p요소, 버튼을 추가하고 내용을 넣는다.
<div class="container-main">
<ul class="l_row">
<li class="l_col l_col_4_12 l_col_tablet_6_12">
<section class="card">
<img class="card-cover" src="images/cover001.png">
<div class="card-contents">
<h2>Edge of tomorrow</h2>
<p>Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled</p>
</div>
<div class="card-controls">
<a class="button" href="">WATCH NOW</a>
</div>
</section>
</li>
<li class="l_col l_col_4_12 l_col_tablet_6_12">
<section class="card">
<img class="card-cover" src="images/cover002.png">
<div class="card-contents">
<h2>Edge of tomorrow</h2>
<p>Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the indusbled</p>
</div>
<div class="card-controls">
<a class="button" href="">WATCH NOW</a>
</div>
</section>
</li>
<li class="l_col l_col_4_12 l_col_tablet_6_12">
<section class="card">
<img class="card-cover" src="images/cover003.png">
<div class="card-contents">
<h2>Edge of tomorrow</h2>
<p>Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry'm Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's sm Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's sm Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's ss standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled</p>
</div>
<div class="card-controls">
<a class="button" href="">WATCH NOW</a>
</div>
</section>
</li>
<li class="l_col l_col_4_12 l_col_tablet_6_12">
<section class="card">
<img class="card-cover" src="images/cover004.png">
<div class="card-contents">
<h2>Edge of tomorrow</h2>
<p>Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled</p>
</div>
<div class="card-controls">
<a class="button" href="">WATCH NOW</a>
</div>
</section>
</li>
<li class="l_col l_col_4_12 l_col_tablet_6_12">
<section class="card">
<img class="card-cover" src="images/cover005.png">
<div class="card-contents">
<h2>Edge of tomorrow</h2>
<p>Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled</p>
</div>
<div class="card-controls">
<a class="button" href="">WATCH NOW</a>
</div>
</section>
</li>
<li class="l_col l_col_4_12 l_col_tablet_6_12">
<section class="card">
<img class="card-cover" src="images/cover006.png">
<div class="card-contents">
<h2>Edge of tomorrow</h2>
<p>Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled</p>
</div>
<div class="card-controls">
<a class="button" href="">WATCH NOW</a>
</div>
</section>
</li>
</ul>
</div>
.card-contents h2 {
color: #EBB3BB;
margin-bottom: 12px;
}
.card-contents p {
box-shadow: inset 0 0 20px blue;
}
버튼 클래스를 생성하여 block속성을 적용하고 중앙 정렬을 한다.
.button {
background-color: black;
color: red;
display: block;
text-align: center;
height: 48px;
line-height: 48px; /*줄높이*/
font-size: 12px;
letter-spacing: 0.2em; /*자간*/
text-indent: 0.2em; /*들여쓰기*/
font-weight: 600;
border-radius: 6px;
}
버튼은 높이 고정과 두줄이 될 가능성이 없기에 줄 높이를 설정한다.
letter-spacing는 텍스트의 문자와 문자 사이 간격(자간)을 지정하는 속성이다.
문자와 문자 사이의 간격을 퍼지게 하거나 더 가깝게 설정할 수 있다.
해당 속성을 사용하여 문자와 문자 사이의 간격을 0.2em만큼 늘린다.
text-indent는 블록에서 텍스트 줄 앞에 놓이는 빈 공간(들여쓰기)의 길이를 설정하는 속성이다.
값을 0.2em 만큼 적용하여 문장들이 문자열을 오른쪽으로 당겨 주변의 문장과 구분 시킨다. (들여쓰기)
콘텐츠 내부 p가 레이아웃이 다르게 나오는 것을 볼 수 있는데 전체정렬하기위해 min height를 설정
car-content p 에서 min-height 400px울 적용하면 깨지지않고 안정적으로 정렬이 된다.
.card-contents p {
min-height: 400px;
box-shadow: inset 0 0 20px blue;
}
하지만 정해진 400px 보다 이상으로 콘텐츠가 더 많아지면 또 정렬이 틀어지기 때문에
높이가 어떻든 관계없이 설정 하기 위해 flex-deraction 을 사용하는데 다음글에 설명
RESULT
'BootCamp Review' 카테고리의 다른 글
2024.08.13~14 (Day 11,12) - HTML/CSS [Position] (0) | 2024.08.18 |
---|---|
2024.08.12 (Day 10) - HTML/CSS [Flexbox III] (0) | 2024.08.18 |
2024.08.07 - Figma(특강) (0) | 2024.08.18 |
2024.08.06 (Day 8) - HTML/CSS [Flexbox] (0) | 2024.08.18 |
2024.08.05 (Day 7) - HTML/CSS (0) | 2024.08.18 |