1. 공간 나누기
<!-- section 템플릿 개념으로 공공재, 레이아웃 (식판) -->
<section class="section theme_purple">
<div class="l_wrapper">
<header class="section-header">
</header>
<div class="section-contents">
Section Contents
</div>
</div>
</section>
<section class="section theme_white">
<div class="l_wrapper">
<header class="section-header">
Section Header
</header>
<div class="section-contents">
Section Contents
</div>
</div>
</section>
</div>
이러한 식으로 section을 통해 서로의 공간을 나누는 것이다.
예를 들면 반찬이 들어간 식판의 공간들을 나누며, 그 반찬이 아니더라도 공공재, 레이아웃 느낌으로 만들어야 한다.
여기서 .section의 역할을 제한시킨다. 아래 2번에 title 컴포넌트를 만들어 역할 제한
- 간격 100px 부여
- 배경색 테마
2. 공간안에서의 컴포넌트 나누기
아래와 같이 헤더 부분에 한덩어리에 타이틀을 같이 한다면 이 컴포넌트는 강제성을 띄게 된다.
여기 공간에는 header-title, description,controls에 관한 내용만 들어와야 하며, 위 부모요소에 flexbox가 들어가 있기 때문에 flex-item 밖에 못온다.
<header class="section-header">
<div class="section-header-title">Title</div>
<div class="section-header-description">Description</div>
<div class="section-header-controls ">Control</div>
</header>
.section-header {
box-shadow: inset 0 0 4px purple;
margin-bottom: 100px;
display: flex;
}
하지만 아래와 같이 하게 된다면 이 타이틀은 독립적인 컴포넌트로 만들어서 이 아래 내용이 아니더라고, 다른 것들이 들어올 수가 있다.
아래 코드처럼 만든 이유는, 위 코드에서 .section-header에 flex를 제거하고, 다른 콘텐츠가 들어올 수 있는 확장성을 위함이다. 그리고 section 이라는 컴포넌트의 역할들을 이 .title로 역할을 분배하는 것이다.
즉 section과 관계 없는 별도의 컴포넌트 .title을 만드는 것이다. 새로운 컴포넌트 생성이니 레이아웃들이 좀 더 직관적이다.
<!-- 의도적으로 section-header와 명확히 구분되는 새로운 컴포넌트로 나눔 -->
<header class="section-header">
<div class="title">
<h1 class="title-headings">Title</h1>
<p class="title-description">Description</p>
<div class="title-controls">Controls</div>
</div>
</header>
.section-header {
box-shadow: inset 0 0 4px purple;
margin-bottom: 100px;
}
// display: flex 삭제
3. 내부 title에 대한 배치
.title {
/* title 하위 가로 배치 */
display: flex;
}
.title-headings {
/* 내부 타이틀 텍스트 만큼 너비가 조정되게! */
flex-basis: auto;
}
.title-description {
/* 가장 많은 텍스트가 추가 될 가능성이 있음. 가장 넓은 영역으로 잡음. 커질 수 있는 크기 제한을 걸었음 */
flex-grow: 1;
max-width: 582px; /* 피그마에서 지정된 사이즈 */
}
.title-controls {
/* 언제나 오른쪽으로 배치 */
margin-left: auto;
}
여기서 title-headings는 내부 타이틀인데 아래쪽 레이아웃과 동일하되, 텍스트가 다르기때문에 flex-basis로 내부 콘텐츠에 맞게 너비 조정한다.
description은 가장 많은 텍스트가 들어가기 때문에 flow-grow:1 로 가용공간 차지, 하지만 크기 제한
controls는 레이아웃으로 잡고 범용적으로 사용될 수 있게 공간을 배치한 것이다.
4. 폰트설정
5. 줄 만들기
이것을 처음 만들때, 저 줄이 계속 줄어드는 문제가 생겼는데, 이것은 shrink: 0을 주지 않아서 줄어드는거였다. 원인을 찾지 못해 네거티브 마진으로 구현을 했는데, 더 쉬운 방법이 있었다.
/* 하위 요소를 Flex Items로 만든다! */
display: flex;
gap: 32px;
align-items: center;
}
/* 가상 요소는 하위 요소로 생성된다. 즉 Flex Items가 될 수 있다. */
.title-description::before {
content: ' ';
background-color: currentColor;
/* 초기값 1, 그러므로 오른쪽 텍스트에 의해 width: 90px이 유지되지 못하고 수축될 수 있음.
그래서 0으로 지정 -> 언제나 90px이 고정이 될 수 있도록 하였다. */
flex-shrink: 0;
width: 90px;
height: 1px;
}
6. 콘텐츠 만들기
위와 같이 만들때 여러가지 방법이 있다. 단순하게 레이아웃이라면 바로 아래와 같이 하고,
단순한 레이아웃이 아니라면 주석이 된 부분으로 처리를 하면 된다
<div class="section-contents">
<ul class="l_gap_row">
<li class="panel">PANEL</li>
<li class="panel">PANEL</li>
<li class="panel">PANEL</li>
</ul>
<!-- 단순 레이아웃이 아닌 다른 것들 들어가며 아래와 같이 작명 -->
<!-- <ul class="panel">
<li class="panel-item">PANEL</li>
<li class="panel-item">PANEL</li>
<li class="panel-item">PANEL</li>
</ul> -->
</div>
CSS는 이러하다.
/* Resets */
body,
p,
ul {
margin: unset;
padding: unset;
}
ul {
list-style-type: none;
}
/* Layouts */
.l_gap_row {
display: grid;
row-gap: 30px;
/* min-width: auto 문제를 컨테이너 관점에서 해결 */
grid-auto-columns: minmax(0, 1fr);
}
위와 같이 minmax를 지정해주면서 min-width:auto로 내부컨텐츠에 따라 크기 조절이 가능하게 만들어준다. 그래서 .l_gap_row의 안정성을 높인다.
.panel-cover {
box-shadow: inset 0 0 20px red;
width: 280px;
}
.panel-contents {
box-shadow: inset 0 0 20px blue;
/* 가변 너비를 가진다. */
/* 내부 콘텐츠 너비와 관계없이 너비 조정 */
flex-basis: 0;
/* flex-basis: 0이므로 flex-grow 비율 너비 조정 */
flex-grow: 1;
/* min-width: auto는 내부콘텐츠 크기로 min-width가 강제된다. */
/* 그래서 이를 없애기 위해 min-width: 0을 지정 */
min-width: 0;
}
}
위와 같은 코드를 주게 되면 아래 그림과 같이 배치가 되는데, 이미지가 들어가는 부분은 고정 px로 지정을 해주고, 옆 contents는 경우는 가변이다. 그래서 flex-grow를 줘서 나머지 가용공간을 차지하게 한다.
안정성을 위해 위 코드를 추가시키며 아래 코드 또한 필수이다.
7. 중요! flex-basis: 0, flex-grow: 1, min-width: 0 자세한 설명 !!
- flex-basis: 0;
- flex-basis는 flex 아이템의 초기 크기를 결정한다. 0으로 설정하면 아이템이 주축(main axis)에 따라 배치될 때, 기본 크기를 0으로 설정한 후, 나머지 공간을 flex-grow에 따라 분배한다. 즉, 이 값이 0일 때 요소의 크기는 완전히 flex-grow와 flex-shrink에 의해 조절된다.
- flex-grow: 1;
- flex-grow는 남아있는 공간을 flex 아이템들이 얼마나 차지할지를 결정한다. 1로 설정하면, 컨테이너 안에 남아있는 공간을 해당 요소가 차지할 수 있다는 의미이다. 여러 요소들이 flex-grow: 1;을 가지고 있으면, 남은 공간이 균등하게 분배된다.
- min-width: 0;
- min-width는 요소가 가질 수 있는 최소 너비를 지정한다. min-width: 0;을 설정하면, 요소의 최소 너비가 0이 되도록 강제되어, flexbox 레이아웃에서 요소가 필요에 따라 완전히 축소될 수 있다. 이는 일부 브라우저에서 요소의 내용 때문에 발생하는 불필요한 크기 고정 문제를 해결하는 데 유용한다.
.l_gap_row {
/* min-width: auto 문제를 컨테이너 관점에서 해결 */
grid-auto-columns: minmax(0, 1fr);
}
8. 클래스명할 때 사용했던 이름들
- cover : 컴포넌트의 대표격 이미지
- header : 컴포넌트에서 header
- title: 컴포넌트에서 title
- main: 컴포넌트에서 main
- contents: 컴포넌트에서 contents
- description: 컴포넌트에서 description
- contents: 컴포넌트에서 contents
- footer:
- controls
- sidebar
9. 내부 콘텐츠 만들기 - 콘텐츠쪽
위와 같이 만들기 위해서는 아래와 같이 코드를 작성했다.
<div class="panel-contents">
<h2 class="panel-title">Take a rest</h2>
<ul class="list">
<li>It has survived not only five centuries.</li>
<li>Why do we use it?</li>
<li>Contrary to popular belief, Lorem Ipsum is not simply random text. It has root.</li>
</ul>
</div>
여기서 list로 클래스명을 지은 이유는, 이 리스트가 범용적으로 사용할 수 있게, 컴포넌트로 만드는 것이다.
원래는 panel-list라고 지을 수 있지만, 위에 이유로 list로 컴포넌트를 만든 것이다.
10. list 동그라미 만들기
처음에 ul에 스타일은 none을 주었다. 그 이유는 무엇일까??
ul {
list-style-type: none;
}
바로 피그마 스타일과도 다르기도 하고, 이쁘지 않기 때문이다.
그래서 위 스타일은 만들기 위해서는 아래와 같은 코드를 주었다.
처음 width와 height를 주면 크기가 변하지 않는다. 그 이유는 이 요소가 inline요소라서 그렇다. inline요소는 높이와 너비가 조절이 안된다. 그래서 이를 블럭으로 바꿔줘야하는데 같은 라인에 있어야 하기 때문에 display: inline-block으로 설정한다.
/* Commons */
.list {
}
.list li + li {
margin-top: 12px;
}
.list li:before {
content: ' ';
background-color: #c89dff;
width: 10px;
height: 10px;
display: inline-block;
border-radius: 50%;
margin-right: 14px;
}
여기에 현재 줄바꿈 되어 있는 것이 점 아래에 있다. 우리가 원하는 디자인은 이게 아니기 때문에 바꿔야 한다..
10-1. 첫번째 방법
.list li {
/* ::before로 만들어진 점과 내부 콘텐츠를 가로로 분리 */
display: flex;
align-items: center;
}
.list li + li {
margin-top: 12px;
}
.list li:before {
content: ' ';
background-color: #c89dff;
width: 10px;
height: 10px;
display: inline-block;
border-radius: 50%;
margin-right: 14px;
/* 점이 절대 작아지지 않게 고정시킴 */
flex-shrink: 0;
}
이 방법에는 문제가 하나 있다.
<ul class="list">
<li>It has survived not only five centuries.</li>
<li>Why do we use it?</li>
<li>Cs<strong>ontrary to popular</strong> belief, Lorem Ipsum is not simply random text. It has root.
</li>
이렇게 중간에 <strong>을 한다면 저러하게 나온다. 그래서 이를 해결하기 위해서는 아래와 같은 방법이 있다.
<span>으로 다 감싸는 것이다. 하지만 이는 코드가 복잡해진다.
<li> <span>Cs<strong>ontrary to popular</strong> belief, Lorem Ipsum is not simply random text. It has
root.</span>
</li>
10-2. 2번째 방법
.list {
/* 점의 width + 점 오른쪽에 margin-right 값을 여유 공간으로 만듦*/
padding-left: 24px;
}
.list li + li {
margin-top: 12px;
}
.list li:before {
content: ' ';
background-color: #c89dff;
width: 10px;
height: 10px;
display: inline-block;
border-radius: 50%;
margin-right: 14px;
/* 점의 width + margin-right만큼 왼쪽으로 이동시키는 효과 */
margin-left: -24px;
}
위와 같이 네거티브 마진을 이용하여 만드는 방법도 있다.
여기에 추가해서 만약 네모난 모양의 리스트를 만들어 달라는 것을 받았다면 아래와 같이 다중 클래스
<ul class="list type_square">
아래와 같이 스타일링을 하면 된다.
.list.type_square li::before {
border-radius: 0;
}
11. 이미지 마크업 및 사이즈 조절하기
img {
max-width: 100%;
vertical-align: top;
}
이미지 초기 스타일 리셋하기
마크업은 아래와 같이 한다.
<div class="panel-cover">
<img class="panel-cover-bg" src="images/cover01.png">
<p class="panel-cover-description">Rest</p>
</div>
위와 같이 마크업 기준으로 할수도 있지만, 이미지를 absolute로 하여 공간 차지를 안하게 할 수도 있다.
아래와 같이 코드를 만들 수 있다.
스태킹 컨텍스트를 사용하여 z-index: -1를 자유롭게 사용할 수 있게 한다.
.panel-cover {
width: 280px;
/* absolute된 요소의 컨테이닝 블록 */
position: relative;
/* z-index: auto가 아닌 값을 넣어 .panel-cover-bg의 새로운 스태킹 컨텍스트가 되게 함 */
z-index: 0;
}
.panel-cover-bg {
/* 상위 요소 중에 position: relative 기준 */
position: absolute;
left: 0;
top: 0;
/* 컨테이닝 블록 기준으로 무조건 가득 채움 */
width: 100%;
height: 100%;
/* 스태킹 컨텍스트에서 가장 맨 밑에 배치 */
z-index: -1;
/* 비율 유지를 위해 넣음 */
object-fit: cover;
}
아래와 같이 됨. 저 이미지가 공간을 차지하지 않음
그리고 안에 텍스트를 배치하기 위해
.panel-cover {
width: 280px;
position: relative;
z-index: 0;
}
.panel-cover-description {
/* 피그마 상 디자인 */
background-color: rgb(98 48 162 / 0.5);
color: var(--color-white);
font-size: 3.2rem;
/* 하위 텍스트 가로세로 중앙 정렬 */
/* height 100%로 부모 높이 받아오는 것 가능 */
height: 100%;
display: flex;
align-items: center;
justify-content: center;
}
위와 같이 하면 아래와 같이 디자인이 가능하다. 나의 경우는 이것을 가상요소로 만들어 작업을 했는데 위와 같은 방법으로 작업하는 것이 좀 더 나은 방법이다. 사진 자체를 앱솔루트로 하여 공간차지하지 않게 만든 후 뒤에 div 하나로 꽉 차게 만들어 배경 컬러를 주고 텍스트를 가운데 정렬하여, 이를 앞으로 오게 하면 된다.
이렇게 이미지를 완료 하였다.
z-index: 0 vs z-index: -1
- z-index: 0: 해당 요소는 같은 스태킹 컨텍스트 내에서 다른 요소들과 비교했을 때 기본적인 위치에 놓이게 된다. 이 값은 특별한 의미 없이 해당 컨텍스트 내에서의 기본 위치를 의미합니다.
- z-index: -1: 이 값은 요소를 같은 스태킹 컨텍스트 내의 다른 요소들 뒤에 위치시키게 된다. 만약 부모 요소가 스태킹 컨텍스트를 생성하는 요소라면, 해당 요소는 부모의 뒤로 보내지지 않고 부모 내에서만 z-index가 낮은 순서대로 배치된다.
- 이를 활용하여 이미지를 뒤로 보내는 역할을 한다.
12. basis를 조절하여 콘텐츠 크기가 자연스럽게 줄어들게 만들기
위와 같이 완성을 하였다. 근데 화면을 줄였을 때, 일정하지 않게 줄어든다 그래서 basis: 0을 주었던 값을 임의로 지정을 해줘서 그 px에 도달하면 줄어들게 만들 수도 있다. 아래와 같이 조절이 가능하다.
.panel-contents {
/* 500px 임의의 설정값으로 동작 변경 -> 창 크기가 작아졌을 때 적절한 시기에 panel-cover, 280px width값을 flex-shrink: 1에 의해 수축 시킬 수 있음 */
flex-basis: 500px;
/* flex-basis: 0이므로 flex-grow 비율 너비 조정 */
flex-grow: 1;
13. 미디어 쿼리를 이용하여 사이즈 줄었을 때 화면 구성
@media (max-width: 768px) {
.title {
display: block;
text-align: center;
}
.title-description {
display: block;
max-width: 320px;
margin: 40px auto;
}
.panel {
display: block;
}
.panel-cover {
width: unset;
여기는 이미지가 absolute로 되어있기 때문에, 이미지 비율 유지되게 만드는 것
aspect-ratio: 12 / 8;
}
}
14. 텍스트의 밑줄 만들기
위와 같이 만들기인데, 마크업은 아래와 같다
<h1 class="title-headings">
START YOUR<br>
<strong>
PORTFOLIO<br>
PROJECT
</strong>
</h1>
css는 아래와 같이 하여, 폰트 크기를 기준으로 박스쉐도우를 움직여 할 수 있다.
.title-headings strong {
box-shadow: inset 0 -0.6em 0 0 orangered;
/* 글자의 폰트크기를 기준으로 박스쉐도우를 움직일 수 있다. */
}
'HTML & CSS' 카테고리의 다른 글
animation , transform (0) | 2024.08.21 |
---|---|
네거티브 마진 % 개념으로 양옆에 사용하게 (0) | 2024.08.21 |
auto-fill vs auto-fit (0) | 2024.08.21 |
Grid ver2 (0) | 2024.08.20 |
Grid (0) | 2024.08.19 |