/* universal selector -> 모든 요소에 대해 적용. 하지만 가상요소는 포함안되서 따로 해줘야함 */
*,
*::before,
*::after {
margin: 0;
padding: 0;
box-sizing: inherit;
...
}
box-sizing을 왜 border-box라고 하지 않고 inherit을 한 이유는 다음과 같다.
...
body {
box-sizing: border-box;
}
inherit 으로 작성해, 만약 특정 클래스의 box-sizing이 border-box가 아니더라도, 해당 클래스의 자식요소는 inherit된 box-sizing을 상속받기에 좀 더 유연하다.
box-sizing: border-box는 width,height의 결정방식을 padding, border를 포함하여 계산됨. 의도한 레이아웃의 크기를 정확히 구현할 수 있음. 필수 설정
(여기서 말하는 lengths는 padding, margin에 해당함)
rem단위는 root의 font-size 기준으로 계산된 비율이라고 했다.
대체로 브라우저의 font-size는 16px인데, 1rem = 16px이면 계산하기 얼마나 귀찮은가, 그래서 계산하기 쉽게
font-size를 전역으로 10px로 고정하고 싶지만, px은 고정된 단위이고 사용자의 기본 폰트 조절 등에 영향을 받지 않는다.
그래서 브라우저의 font-size: 16px을 이용한다.
계산상 10px은 브라우저의 font-size의 62.5%에 해당한다. 이를 reset.scss에 적용한다.
이러면 이제 rem 단위를 사용하면서 px을 rem으로 변환할때 * 0.1 만 하면 되니 편해지고 유연하게 대응이 가능하다.
(위는 구시대적 방식임. 현대 css의 안티패턴)
html {
font-size: 설정안함 (브라우저 기본값 사용)
}
// SCSS 함수로 계산 자동화
@function rem($px) {
@return #{$px / 16}rem;
}
외의 고정된 elements 레이아웃, 아이콘, 보더 등은 px쓰는게 적절하다
.text {
font-size: rem(18);
line-height: rem(28);
margin: rem(24) 0;
padding: rem(16);
}
.card {
padding: rem(20);
margin-bottom: rem(32);
border-radius: rem(8);
}
1) display: block
- 한 줄을 모두 차지함
- width, height 설정 가능
- margin, padding 모든 방향 적용 가능
- <div> <p> <h1> <header> 등
2) display: inline
- 줄바꿈 없이 옆으로 나란히 배치
- width, height 설정 불가
- margin, padding은 좌우만 가능
- <span> <a> <em> <strong> 등
3) display: inline-block
- 옆으로 나란히 배치 (inline 속성)
- width, height 설정 가능 (block 속성)
- margin, padding 모든 방향 적용 가능 (block 속성)
- <button> <input> <select> 등
예를들어 <a> 태그를 사용하고, 이는 기본적으로 display: inline 속성을 가진다.
따라서 width, height 속성이 무시되고, padding/margin의 상하 간격이 무시됨.
이런 문제를 해결하고 display: block특성도 가지게 하기 위해 display: inline-block사용.
display: inline 속성은 쉽게 말해 text의 속성을 따른다고 보면 된다.
즉, 부모의 text-align: center 하나로 a태그자체를 가운데 정렬이 가능하다.
(button태그였다면 기본적으로 inline-block임)
동일한 selector에 여러 스타일을 적용할경우, CSS는 Cascade라는 스타일 우선순위 적용 결정 알고리즘을 가진다.
!important (가장 높음)::hover가 우선순위에 밀리면 적용되지 않음)&(앰퍼샌드) 는 sass문법으로 scss에서 제일 많이 쓰는거 같다.
이 설명이 끝이고, 이로 인한 응용 가능성이 매우 높다
.parent {
color: blue;
&:hover { // css 컴파일 시 .parent:hover{}
color: red;
}
}
.btn {
padding: 10px;
&.active { // .btn.active 일때 적용
background: red;
}
&.disabled { // .btn.disabled 일때 적용
opacity: 0.5;
}
}
.block {
display: block;
&__element { // .block__element 컴파일
color: blue;
&--modifier { // .block__element--modifier 컴파일
font-weight: bold;
}
}
&--theme-dark { // .block--theme-dark 컴파일
background: black;
}
}
.input {
border: 1px solid gray;
&[disabled] { opacity: 0.5; }
}
.item {
margin-top: 0;
& + & { // 두번째 .item 부터 적용
margin-top: 16px;
}
}
중첩된 부모-자식 클래스에서 &를 쓸때 주의해야함.
예를들어, 카드컴포넌트에 hover시 rotate되며 카드 뒷면을 보여주고싶은데,
앞면 뒷면 클래스를 .card__side--front .card__side--back 으로 나눴다고 가정.
.card{
perspective: 170rem;
...
&:hover {
&__side--front { // 이딴식으로 쓰면 망한다.
transform: rotateY(180deg);
}
}
}
위 코드의 &:hover블록의 컴파일 결과는 다음과 같다.
.card:hover hover__side--front{}
참으로 개떡같지 않은가. &는 직전 부모를 참조한다는 사실을 잊지마라.
그럼 해당 요구사항은 다음과 같이 수정 가능하다.
.card{
// "perspective" 란 3D 변환 요소들이 화면에서 어떻게 보일지 결정. 뷰어와 3D 객체 사이의 거리를 나타냄.
// 너무 가까우면 왜곡이 심하고, 너무 큰값이면 평면적인(2D) 효과로 보임, 'none' 이면 2D효과로 보임.
perspective: 140rem;
...
&:hover &__side--front {
transform: rotateY(180deg);
}
}
비슷한 예시로, hover시에 hover되지 않는 요소들에 대한 스타일정의는 다음과 같이 적용 가능하다.
.부모{
&:hover &__photo:not(:hover) {
transform: scale(.95);
}
}
위의 예시들은 전부 부모-자식 클래스 관계에서의 스타일 적용이다.
.부모 {
&:hover .자식 {}
}
위 구조는 다음과 같으며
.부모 {
&:hover{
.자식 {}
}
}
부모-자식 간 클래스 일때만 적용된다.
인라인으로 &:hover공백.자식{}
여기서 공백으로서 자식 선택자가 적용된다.
+ 사용~ 사용<form class="form">
<input class="input"/>
<label class="label"></label>
</form>
이 구조에서 input - label 형제 요소들의 스타일적용의 예시.
.form {
.input {}
.label {}
.input:focus + .label { // 혹은 ~
label에 스타일
}
}
위 html구조처럼 label이 input 바로 다음에 놓여있기때문에 +를 사용 가능.
너무 많다... :hover :active :first-child :last-child 등등,, 알아서 잘 써라
pseudo class를 부정하기 위한 pseudo class
.list {
&:not(:last-child){
// ex) 마지막요소 빼고 아래 적용
margin-bottom: 20px;
}
}
::after 가상요소 ::after와 ::before의 차이는 삽입되는 위치의 차이.
가장 많이 사용되는 용도는 리스트의 불릿아이콘, 화살표 아이콘 등
장식요소에 불과하기때문에 굳이 html에 포함시키지 않아서 사용함.
.btn {
position: relative;
...
&::after {
content: "";
position: absolute;
...
}
}
부모가 position: relative 면 position: absolute가 적용되는데,
위 코드의 .btn 이 부모인가?
아니다. 즉, Pseudo Class는 자식요소처럼 작동함
z-index 속성은 항상 position 요소가 존재할때만 작동한다
반응형 UI를 구성할때 Media Query설정은 필수이고, 대부분의 경우 Mobile-First Design을 적용한다.
다만 일부의 경우 Desktop-First Design도 적용하긴 하기에 둘다 정리한다.
SCSS로 @mixin을 통해 구성한다.
이 경우 defualt style이 mobile뷰에 해당하고, 미디어쿼리를 적용할 때는 tablet > desktop 순으로 작성해야한다.
@mixin respond($breakpoint) {
@if ($breakpoint == tablet) {
@media (min-width: 768px) {
@content;
}
}
@if ($breakpoint == desktop) {
@media (min-width: 1024px) {
@content;
}
}
}
사실 거의 안쓴다, TailwindCSS, MaterialUI 등 프레임워크도 mobile-first만을 지원하지만 특수한 경우를 위해서라면,, defualt style 이 desktop뷰에 해당하고, 큰 화면 순으로 미디어쿼리를 적용한다.
@mixin respond($breakpoint) {
@if ($breakpoint == small-desktop) {
@media (max-width: 1200px) { @content; }
}
@if ($breakpoint == tablet) {
@media (max-width: 900px) { @content; }
}
@if ($breakpoint == phone) {
@media (max-width: 600px) { @content; }
}
}
현대 css에서 가장 많이 쓰일 속성인거같다. display: flex 를 사용하면 쉽게 반응형 레이아웃을 구성 가능하다.
** display: inline-flex 도 있지만 쓸 이유가 없는 쓰레기속성이다.
display: flex 를 적용하는, 즉 컨테이너 클래스에 사용가능한 속성들을 정리해본다.
우선 flexbox는 항상 X-axis와 Y-axis를 기준으로 main-axis와 cross-axis가 정해져서 사용된다.

일단 저런방향으로 axis가 존재한다는걸 인지하고 접근해야한다.
row 계열일때 main-axis는 X축, column 계열일때 main-axis는 Y축이 된다.
아래 그림으로 이해가 빠를것이다.

x만큼의 간격을, 아이템들 사이에는 2x만큼의 간격을만약 아이템들의 높이가 제각각 이라고 가정하면 이해가 쉬울것이다.
개별 아이템들에 대한 속성이 align-items였다면, 이는 한단계 높은 범위, 즉 flex 라인 자체의 위치를 결정한다.
이 속성은 flex-wrap: wrap 일때에만 의미가 있다.
컨테이너 안의 개별 아이템들에 대한 속성이다.
-> 최상단 부모에 align-items: center가 적용되어있지만 일부 자식 요소는 해당 컨테이너를 전부 채워야 할 경우, 해당 자식 요소에만 align-self: stretch를 적용할 수 있다.
이는 부모 자식간의 중첩flex일지라도 적용이 가능하다.
**align-self를 적용한 자식클래스에 display:flex, align-items등 적용한 상태여도 무방
0으로 설정할 경우 줄어들지 않고 심지어 flex-basis로 width를 고정했다면 해당 값이 뷰포트가 줄어들어도 고정됨.
즉, 새로운 flex 라인 자체를 생성하지 않고 오버플로우를 발생시킴.
위 세가지 옵션을 한번에 쓰기위한 값. ex) flex: 0 1 200px;
자주 사용되는 flex: 1 은 아이템들이 남은 공간을 동등하게 나누어서 최대한 차지하려고 만들게된다.
** 아이템들에게 공통적으로 적용해야 의미가 있다
.sidebar-layout {display: flex;}
.sidebar { flex: 0 0 250px; } // 고정 사이드바
.content { flex: 1; } // 나머지 공간
예를들어 row방향의 flex박스에 정렬이 필요할때,
justify-content: space-between 처럼 균등 분배하는게 아닌, 일부 아이템의 위치만 조정하고싶을때, 원하는 요소에 flex: 1을 사용해도 되고, margin-left: auto 혹은 margin-right: auto를 사용할 수 있다.
차이점으로는, flex: 1는 크기 조절에 초점을 맞춘것이고, margin-left: auto는 위치 조절에 초점을 맞춘 것이다. 요소에 배경색을 입힐경우 차이를 볼 수 있다.
display: grid 로 사용가능하다. flex-box가 1차원공간을 다뤘다면, 이는 2차원 공간을 다룬다.
복잡한 레이아웃 구성에 적합하다.

grid template의 row설정을 하며, row별 높이를 지정한다.
위 이미지의 예시로는 다음과 같이 표현이 가능하다.
grid-template-rows: 150px 150px;
grid-template-rows: repeat(2, 150px);
grid template의 column설정을 하며, column별 너비를 지정한다.
위 이미지의 예시로는 다음과 같이 표현이 가능하다.
grid-template-columns: 150px 150px 150px;
grid-template-rows: repeat(3, 150px);
grid-template-columns: repeat(3, 1fr) 이라고 할 경우, 세 컬럼이 모두 동등하게 공간을 차지한다. 혹은 1fr 3fr 1fr 이런식으로 사용한다면 비율에 맞게 공간을 분배한다.
grid-template-columns: repeat(auto-fill, 100px) 와 같이 사용한다.grid-template-columns: repeat(auto-fit, 100px) 와 같이 사용한다.minmax(최소값, 최대값) 처럼 사용하며, 매우 유연하고 실무에서는 이를 주로 쓴다row, column의 셀 사이 gap을 지정하며, 같을 경우 gap만으로 정의한다.
정의한 그리드 셀의 갯수보다 아이템이 많을때 어떤방향으로 넘칠지 결정 가능하다.
** dense를 추가하면 빈 셀 없이 모든 아이템들이 셀을 채움. (full packed grid)
ex) grid-auto-flow: row dense;
넘친 아이템의 높이를 결정
넘친 아이템의 너비를 결정
셀을 차지하는 아이템들의 positioning (stretch / center/ start/ end)
vertically,horizontally positioning
flex-box와 동일
flex-box와 동일
auto-fit과, minmax()를 활용해서 반응형 그리드를 만들 수 있다.
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)) 처럼 선언할 경우,
브라우저의 사이즈에 따라 하나의 셀은 최소단위 200px을 지키기 위해 width가 부족할 경우, 새로운 row로
아이템을 이동시킴.
** 이 경우 grid-auto-rows 사용
각 아이템을 cell이라고 부르는데, display: grid의 cell의 위치를 다른 cell위치에 명시적으로 옮기고 싶을 경우, row가 시작하는 지점, 끝나는 지점, column의 시작 좌표, 끝나는 좌표 정보로 이동시킬 수 있다.
위 이미지를 참고하여 아래처럼 표현이 가능하다.
grid-row: start point / end point;
grid-column: start point / end point;
혹은
grid-area: row-start / column-start / row-end / column-end;
grid-row 혹은, grid-column의 좌표를 표현할때 다음과 같이 표현도 가능하다.
span: 좌표 대신 셀의 갯수로 표현 가능
ex) grid-row: 3 / span 5; => 3번 row부터 cell 5개 기준으로 row를 차지함.
-1: 차지할 수 있는 모든 공간을 차지
ex) grid-column: 1 / -1;