minstudio

CSS 기본 문법과 모던 선택자 (Nesting 포함)

1994년
CSS 최초 제안 하콘 비움 리가 웹 디자인을 위한 스타일 시트 개념 제안.
1996년
CSS Level 1 (CSS1) 폰트, 색상, 여백 등 기본적인 텍스트 서식과 박스 모델 지원.
1998년
CSS Level 2 (CSS2) 요소의 절대 위치 지정(Positioning), z-index, 미디어 타입 도입.
2011년
CSS 2.1 표준화 확정 웹 브라우저들의 상호 호환성을 위한 버그 수정 및 안정화.
2010년대 후반 ~ 현재
CSS3 (모듈화 시대) 🚀 Flexbox, Grid, 애니메이션, 미디어 쿼리 등 독립적인 모듈 업데이트.

CSS (Cascading Style Sheets)는 HTML 문서의 디자인과 레이아웃을 담당하는 스타일 시트 언어입니다. 1994년 하콘 비움 리(Håkon Wium Lie)에 의해 최초 제안되었습니다.

초기 웹은 디자인 요소 없이 텍스트 중심이었으나, CSS의 등장으로 콘텐츠(HTML)와 디자인(CSS)의 완벽한 분리가 가능해졌습니다.

💡 폭포수처럼 흐르는 스타일 (Cascading) CSS의 'Cascading'은 폭포라는 뜻으로, 우선순위에 따라 부모 요소의 스타일이 자식 요소로 흐르며(상속), 중복된 규칙 중 가장 구체적인 규칙이 적용되는 원리를 의미합니다.

웹 디자인 레이아웃의 진화

1세대 (1990s) 테이블 레이아웃 시대

CSS가 제대로 지원되지 않던 시절, <table> 태그를 잘라 붙여 억지로 레이아웃을 잡았습니다. HTML 문서 안에 디자인 코드가 뒤섞여 있어 유지보수가 끔찍했던 암흑기입니다.

2세대 (2000s) Float & Positioning 시대

본격적으로 웹 표준이 자리 잡으며, <div> 박스들을 floatposition 속성으로 이리저리 띄우고 배치하여 레이아웃을 구성했습니다.

3세대 (2010s) 반응형 웹(Responsive Web) 시대

스마트폰 폭발적 보급으로 화면 크기가 다양해졌습니다. 미디어 쿼리(Media Query)의 등장으로 모바일, 태블릿, PC 등 화면 크기에 맞춰 디자인이 실시간으로 변하는 반응형 웹이 필수 표준이 되었습니다.

4세대 (현재) 모던 레이아웃 (Flexbox & Grid) 시대 🚀

수학적인 계산과 꼼수로 레이아웃을 잡던 시대가 끝났습니다! 레이아웃을 위해 탄생한 Flexbox(1차원 배열)CSS Grid(2차원 배열) 덕분에 아무리 복잡한 디자인도 깔끔하게 제어할 수 있게 되었습니다.

CSS 발전에 따른 시각적 변화 예시

과거부터 현재까지 CSS가 발전함에 따라, 요소를 꾸미는 방식이 얼마나 다양해졌는지 시각적으로 확인할 수 있습니다.

CSS1 (1996): 텍스트와 배경색 중심의 단순한 꾸밈
CSS2 (1998): 박스 모델과 테두리의 등장으로 레이아웃 형성
CSS3 (현재): 그림자, 모서리, 애니메이션, Flexbox 결합 🚀

🎨 CSS (Cascading Style Sheets)란?

HTML이 뼈대라면 CSS는 피부와 옷입니다. 1996년 W3C에서 처음 도입된 이후 웹 디자인의 핵심 언어로 자리 잡았습니다.

명시도 (Specificity) 우선순위

동일한 요소에 스타일이 충돌할 때, 우선순위가 높은 쪽이 이깁니다!

!important
인라인 (style="")
#id
.class
태그 (div, p)
전체 (*)
우선순위 높음 우선순위 낮음

CSS의 기본 구조

CSS는 "누구에게(선택자)", "무엇을(속성)", "어떻게(값)" 적용할지를 정의하는 아주 직관적인 구조로 되어있습니다.

선택자 (Selector) h1
{
속성 (Property) color
:
값 (Value) red
;
}

다양한 CSS 선택자 가이드

원하는 HTML 요소를 정확하게 콕 집어내기 위해 다양한 선택자를 조합할 수 있습니다.

기본 선택자
  • 태그 선택자: div, p
    HTML 태그 이름을 그대로 사용합니다.
  • 클래스 선택자: .card, .btn
    점(.)으로 시작하며, 여러 요소에 중복 사용 가능합니다.
  • 아이디 선택자: #header, #logo
    해시(#)로 시작하며, 페이지 내 단 하나만 존재해야 합니다.
  • 전체 선택자: *
    모든 요소를 선택합니다. (주로 초기화에 사용)
복합 (결합) 선택자
  • 자손 선택자: div p (공백)
    div 안에 있는 모든 p 요소를 선택합니다.
  • 자식 선택자: ul > li
    ul의 바로 아래 직계 자식인 li만 선택합니다.
  • 인접 형제: h1 + p
    h1 바로 다음에 오는 형제 p 요소 하나만 선택합니다.
  • 일반 형제: h1 ~ p
    h1 다음에 오는 모든 형제 p 요소를 선택합니다.
가상 클래스 (상태) 선택자
  • :hover .btn:hover
    요소 위에 마우스를 올렸을 때의 상태
  • :active .btn:active
    요소를 마우스로 클릭하고 있는 찰나의 상태
  • :nth-child(n) li:nth-child(2)
    형제 요소 중 두 번째 요소를 선택 (홀/짝수도 가능)
  • :not(A) p:not(.error)
    .error 클래스를 가지지 않은 모든 p 요소 선택

CSS를 HTML에 적용하는 3가지 방법

적용 방법 특징 및 사용처 실무 권장도
인라인 스타일 (Inline) HTML 태그의 style 속성에 직접 작성합니다. 재사용이 불가능하고 유지보수가 어려워 추천하지 않습니다.
내부 스타일 시트 (Internal) HTML 문서 안의 <style> 태그에 작성합니다. 단일 문서에 적합하지만, 여러 페이지 공유는 불가능합니다.
외부 스타일 시트 (External) .css 파일을 따로 만들고 <link>로 연결합니다. 디자인과 구조를 완벽히 분리하므로 실무에서 가장 권장됩니다.

아래 예제에서 인라인 스타일이 내부 스타일보다 우선순위가 높게 적용되는 것을 확인해 보세요.

심화 학습

CSS 선택자(Selectors)와 네이티브 중첩(Nesting)

CSS를 작성하다 보면 "도대체 왜 내가 준 색상으로 안 변하는 거지?"라며 분노하게 되는 순간이 반드시 찾아옵니다. 이 모든 원인은 브라우저가 스타일의 우선순위를 결정하는 명시도(Specificity) 점수를 제대로 이해하지 못했기 때문입니다.

⚖️ CSS 명시도 점수 배점표 (누가 이길까?)

👑 명시도 (Specificity) 계급표 !important 인라인 스타일 #아이디 (ID) .클래스 (Class) 태그 10,000점 1,000점 100점 10점 1점 복잡하게 얽힌 선택자 ul .list li a 태그 3개(3) + 클래스 1개(10) 13점 VS 단순하지만 강력한 ID #nav-link ID 1개(100) 100점 WINNER! 🏆

아무리 길고 복잡하게 태그와 클래스를 여러 개 적어두어 봤자(예: div ul .list li a = 14점), 단 1개의 ID 선택자(#nav-link = 100점)를 이길 수 없습니다. 따라서 실무에서는 CSS 충돌을 피하기 위해 가급적 ID를 스타일링에 사용하지 않고, 오직 Class만 사용하여 점수를 평준화하는 것이 암묵적인 규칙입니다. (!important는 핵무기 같은 존재이므로 최후의 수단으로만 써야 합니다.)

✨ 최신 모던 CSS 기술: 네이티브 중첩 (Native CSS Nesting)

과거에는 부모/자식 관계를 표현하기 위해 선택자를 매번 반복해서 적어야 했습니다. 하지만 2023년 말부터 모든 최신 브라우저가 Sass/SCSS 없이 순수 CSS만으로 코드를 중첩(Nesting)하는 문법을 공식 지원하기 시작했습니다.

  • 앰퍼샌드(&)의 활용

    부모 블록 안에서 & 기호를 사용하면 부모 선택자를 그대로 가져옵니다. 코드가 획기적으로 짧아지고, HTML 구조와 CSS 구조가 거울처럼 똑같이 매칭되어 유지보수성이 극대화됩니다.

<div class="card">
  <h2>Hello CSS!</h2>
  <p>속성과 값을 변경하여 디자인을 바꿔보세요.</p>
</div>

<style>
/* --- 아래는 적용 방법 예시 --- */
/* 내부 스타일 시트 (Internal) */
.box {
  background-color: #3b82f6; /* 파란 배경 */
  color: white; /* 흰색 텍스트 */
  padding: 1.5rem;
  border-radius: 8px;
  text-align: center;
  font-weight: bold;
}
</style>

<!-- 인라인 스타일이 내부 스타일을 덮어씁니다! -->
<div class="box" style="background-color: #ef4444; /* 인라인 스타일 (빨간색으로 강제 적용) */">
  나는 파란색이어야 하지만, 인라인 스타일 때문에 빨간색입니다!
</div>
<!-- ====== CSS 선택자(Selectors)와 네이티브 중첩(Nesting) ====== -->
<div style="margin: 30px 0; border-top: 1px solid #475569;"></div>
<style>
/* 1. 다양한 복합 선택자 */
.card > h2 { color: #ef4444; margin-bottom: 5px; } /* 자식: 바로 밑의 h2만 */
.card h2 { color: #3b82f6; }  /* 자손: 자식의 자식까지 포함한 모든 h2 (위 규칙이 없었다면 파란색) */
.title + p { font-weight: bold; color: #10b981; }  /* 인접 형제: 바로 뒤에 오는 p 1개만 초록색/굵게 */
.title ~ p { opacity: 0.6; } /* 일반 형제: 뒤에 오는 모든 p 반투명 */

/* 2. 속성 선택자 */
input[type="password"] { background: #fee2e2; border: 1px solid #ef4444; padding: 4px; }
a[href^="https"] { color: #10b981; font-weight: bold; text-decoration: none; } 

/* ======================================= */
/* 3. 🔥 최신 문법: Native CSS Nesting 🔥 */
/* ======================================= */
.article {
  padding: 20px;
  background: #f8fafc;
  border-radius: 8px;
  border: 1px solid #cbd5e1;
  margin-top: 20px;

  /* .article 안의 p 요소 */
  p {
    line-height: 1.6;
    color: #334155;
    margin: 5px 0;
  }

  /* .article 에 마우스를 올렸을 때 (& = .article) */
  &:hover {
    box-shadow: 0 10px 15px -3px rgba(0,0,0,0.1);
    border-color: #94a3b8;
  }

  /* .article 안의 자식 중 .highlight 클래스 */
  & > .highlight {
    background: #fef08a;
    padding: 2px 6px;
    border-radius: 4px;
    font-weight: bold;
    display: inline-block;
  }
}
</style>

<!-- HTML 구조 -->
<div class="card" style="padding:15px; border:1px solid #ccc; border-radius:8px; margin-bottom:15px;">
  <h2>카드 제목 (자식)</h2>
  <div>
    <h2>카드 안의 다른 제목 (자손)</h2>
  </div>
</div>

<h3 class="title">형제 선택자 테스트</h3>
<p>첫 번째 단락 (인접 형제)</p>
<p>두 번째 단락 (일반 형제)</p>
<p>세 번째 단락 (일반 형제)</p>

<div style="margin: 20px 0;">
  <input type="text" placeholder="일반 텍스트" style="padding: 4px;">
  <input type="password" placeholder="비밀번호 입력">
  <br><br>
  <a href="https://google.com">HTTPS 보안 링크</a> | <a href="http://example.com">HTTP 일반 링크</a>
</div>

<div class="article">
  <h4>CSS Nesting 테스트 영역 (마우스를 올려보세요!)</h4>
  <p>이 단락은 article 내부의 p 요소 스타일이 적용되었습니다.</p>
  <div class="highlight">나는 하이라이트 된 자식 요소입니다.</div>
</div>
실행 결과
CSS 기본 문법과 모던 선택자 (Nesting 포함) | Minstudio