๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ

๐Ÿ‘ฉ๐Ÿป‍๐Ÿ’ปSTUDY/CSS

[CSS] CSS๋ฐฉ๋ฒ•๋ก (BEM/OOCSS/SMACSS)

๋ฐ˜์‘ํ˜•

CSS ๋ฐฉ๋ฒ•๋ก (BEM/OOCSS/SMACSS)

CSS ์„ค๊ณ„์˜ ์ค‘์š”์„ฑ

  • ์ฝ”๋“œ์˜ ์žฌ์‚ฌ์šฉ์„ฑ์„ ์œ„ํ•ด
  • ์‰ฝ๊ฒŒ ์œ ์ง€๋ณด์ˆ˜ ํ•˜๊ธฐ ์œ„ํ•ด
  • ํ™•์žฅ์„ ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ•˜๊ธฐ ์œ„ํ•ด
  • ํด๋ž˜์Šค๋ช…์œผ๋กœ๋„ ๋ฌด์Šจ ์˜๋ฏธ์ธ์ง€ ์˜ˆ์ธก ๊ฐ€๋Šฅํ•˜๋„๋ก ํ•˜๊ธฐ ์œ„ํ•ด

 

BEM (Block Element Modifier)

  • Block, Element, Modifier ๋กœ ๋‚˜๋ˆ„์–ด ์ปดํฌ๋„ŒํŠธ ๊ธฐ๋ฐ˜์˜ ์›น ๊ฐœ๋ฐœ ์ ‘๊ทผ๋ฒ• ์ค‘ ํ•˜๋‚˜.
  • ์œ ์ € ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๋…๋ฆฝ๋œ ์—ฌ๋Ÿฌ ๊ฐœ์˜ ๋ธ”๋ก์œผ๋กœ ๋ถ„๋ฆฌํ•˜์ž๋Š” ๊ฒƒ์ด ๋ชฉํ‘œ
  • ๋ณต์žกํ•œ UI๋ฅผ ๊ฐ€์ง„ ํŽ˜์ด์ง€์˜ ์ธํ„ฐํŽ˜์ด์Šค ๊ฐœ๋ฐœ ํ™˜๊ฒฝ์„ ์‰ฝ๊ณ  ๋น ๋ฅด๊ฒŒ ํ•˜๋ฉฐ, ์ฝ”๋“œ์˜ ์žฌํ™œ์šฉ์„ ๋†’์ผ ์ˆ˜ ์žˆ๋‹ค.
  • ํด๋ž˜์Šค๋ช…์ด ์šฉ๋„, ํ˜•ํƒœ๋ฅผ ์˜๋ฏธํ•˜๋ฏ€๋กœ ์ง๊ด€์ ์ด๋‚˜ ๊ธธ๊ณ  ๋ณต์žกํ•ด์ง€๋Š” ๊ฒƒ์ด ๋‹จ์ .

1) Block

  • ์žฌ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ์ปดํฌ๋„ŒํŠธ. (์ฝ”๋“œ์˜ ๊ตฌ์กฐ์  ๋ฉ์–ด๋ฆฌ)
  • ํด๋ž˜์Šค๋ช…์€ ํ•˜๋‚˜์˜ ๋‹จ์–ด ์‚ฌ์šฉ, ๊ธธ์–ด์งˆ ๊ฒฝ์šฐ ๋‹จ์ผ ํ•˜์ดํ”ˆ(-)์œผ๋กœ ๊ตฌ๋ถ„

    • ๋ธ”๋ก์˜ ๋ชฉ์ ์œผ๋กœ ๊ธฐ์ˆ ๋˜๋ฉฐ, ์ƒํƒœ๋ฅผ ๋‚˜ํƒ€๋‚ด์ง€ ์•Š๋Š”๋‹ค.

      <!-- Correct :: ๋ฌด์—‡์ธ์ง€ ์ •ํ™•ํžˆ ๊ธฐ์ˆ . -->
      <div class="error"></div>
      <!-- Incorrect :: ์–ด๋–ป๊ฒŒ ํ‘œํ˜„ ๋˜๋Š” ์ƒํƒœ๋ฅผ ๋‚˜ํƒ€๋‚ด์ง€ ์•Š๋Š”๋‹ค. -->
      <div class="red-text"></div>
      

 

2) Element

  • ๋ธ”๋ก ์™ธ๋ถ€์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๋Š” ๋ธ”๋ก ๋‚ด์˜ ์š”์†Œ๋ฅผ ๋œปํ•œ๋‹ค.
  • ๋ธ”๋ก ๋งฅ๋ฝ์—์„œ๋งŒ ์˜๋ฏธ๊ฐ€ ์žˆ์–ด์•ผ ํ•จ
<form class="search-form">
  <input class="search-form__input">
  <button class="search-form__button"></button>
</form>
/* Good */
.search-form__input {...}
.search-form__button {...}

/* Bad */
.search-form .search-form__input {...}
button.search-form__button {...}
  • ํ•œ ์š”์†Œ๋Š” ํ•ญ์ƒ ๋ธ”๋ก์˜ ๋ถ€๋ถ„์ด์–ด์•ผ ํ•˜๋ฉฐ, ๋ธ”๋ก์œผ๋กœ๋ถ€ํ„ฐ ๋ถ„๋ฆฌ๋˜์–ด ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๋‹ค.
<!-- Correct -->
<form class="search-form">
  <input class="search-form__input">
  <button class="search-form__button">Search</button>
</form>

<!-- Incorrect -->
<form class="search-form"> 
</form>
<!-- 'input'์œผ๋กœ ๊ถŒํ•œ๋‹ค. -->
<input class="search-form__input">
<!-- 'button'์œผ๋กœ ๊ถŒํ•œ๋‹ค. -->
<button class="search-form__button">Search</button>
  • ํ•œ ๋ธ”๋ก์€ DOM tree ์—์„œ ์—ฌ๋Ÿฌ ๊ฐœ๋กœ ์ค‘์ฒฉ๋œ ์š”์†Œ๋“ค์„ ๊ฐ€์งˆ ์ˆ˜ ์žˆ๋‹ค.
<!-- (1) -->
<div class="block">
  <div class="block__elem1">
    <div class="block__elem2">
      <div class="block__elem3"></div>
    </div>
  </div>
</div>

<!-- (2) -->
<div class="block">
  <div class="block__elem1">
      <div class="block__elem2"></div>
  </div>
  <div class="block__elem3"></div>
</div>
  • ์œ„์˜ ๋ธ”๋ก ๊ตฌ์กฐ๋“ค์„ BEM ๋ฐฉ๋ฒ•๋ก ์—์„œ ์š”์†Œ๋“ค์˜ ๋ชฉ๋ก๋“ค๋กœ ํ‘œํ˜„. :: ๋ธ”๋ก ๊ตฌ์กฐ๊ฐ€ ๋ณ€ํ•˜๋”๋ผ๋„((1)์—์„œ (2)๋กœ ๋ณ€๊ฒฝ) ์š”์†Œ๋“ค์˜ ๊ทœ์น™๊ณผ ์ด๋ฆ„์€ ๋˜‘๊ฐ™์ด ์œ ์ง€๋˜์–ด์•ผ ํ•˜๋ฏ€๋กœ.
.block {...}
.block__elem1 {...}
.block__elem2 {...}
.block__elem3 {...}

3) Modifier

  • ๋ธ”๋ก์ด๋‚˜ ์š”์†Œ์˜ ๋ชจ์–‘ (color, size) / ์ƒํƒœ (disabled, checked)๋ฅผ ์ •์˜.
  • block__elem--modifier , block--modifier ํ˜•ํƒœ๋กœ ์‚ฌ์šฉ.
  • block__elem1__elem2์€ ์ž˜๋ชป๋œ ๋ฐฉ๋ฒ•.
<!-- Correct -->
<form class="search-form">
  <div class="search-form__content">
    <input class="search-form__input">
    <button class="search-form__button">Search</button>
  </div>
</form>

<!-- Incorrect -->
<form class="search-form">
  <div class="search-form__content">
    <!-- 'search-form__input' or 'search-form__content-input' ์œผ๋กœ ๊ถŒํ•œ๋‹ค. -->
    <input class="search-form__content__input">
    <!-- 'search-form__button' or 'search-form__content-button' ์œผ๋กœ ๊ถŒํ•œ๋‹ค. -->
    <button class="search-form__content__button">Search</button>
  </div>
</form>
  • modifier์˜ ์ด๋ฆ„์€ ๋ธ”๋ก์ด๋‚˜ ์š”์†Œ ์ด๋ฆ„์œผ๋กœ๋ถ€ํ„ฐ ์‹ฑ๊ธ€ ์–ธ๋”์Šค์ฝ”์–ด(_)๋กœ ๋ถ„๋ฆฌ๋œ๋‹ค.

    • block-name_modifier-name
    • block-name__element-name_modifier-name
    • block-name_modifier-name_modifier-value
    • block-name__element-name_modifier-name_modifier-value
    <!-- 'search-form' :: block / 'theme' :: modifier / 'islands' :: value  -->
    <form class="search-form search-form_theme_islands">
      <input class="search-form__input">
      <button class="search-form__button search-form__button_size_m">Search</button>
    </form>
    
    <!-- ๋‘ ๊ฐœ์˜ ๊ฐ™์€ modifiers๋Š” ๋‹ค๋ฅธ value๋ฅผ ๊ฐ€์ง„๋‹ค. -->
    <form class="search-form
                 search-form_theme_islands
                 search-form_theme_lite">
      
      <input class="search-form__input">
      
      <button class="search-form__button
                     search-form__button_size_s
                     search-form__button_size_m">
        Search
      </button>
    </form>
    

 

OOCSS (Object Oriented CSS)

OOCSS๋Š” ๊ฐ์ฒด ์ง€ํ–ฅ์— ๋”ฐ๋ผ ๊ณ ์•ˆ๋œ ์„ค๊ณ„ ๋ฐฉ์‹

  • ๊ตฌ์กฐ์™€ ์™ธํ˜•์˜ ๋ถ„๋ฆฌ (Separate Structure and skin)
  • ์ปจํ…Œ์ด๋„ˆ์™€ ๋‚ด์šฉ ๋ถ„๋ฆฌ (Separate container and content)
  • OOCSS style

1) ๊ตฌ์กฐ์™€ ์™ธํ˜•์˜ ๋ถ„๋ฆฌ

๊ธฐ๋ณธ์ ์ธ ๊ตฌ์กฐ์™€ ๋ฐ˜๋ณต ์ •์˜๋˜๋Š” ์™ธํ˜•์€ ๋”ฐ๋กœ ์ •์˜. (๊ณตํ†ต ์Šคํƒ€์ผ ์ถ”์ƒํ™”)

  • ๊ตฌ์กฐ : width, height, border, padding, margin
  • ์™ธํ˜• : color, border-color, font-color, background-color

 

2) ์ปจํ…Œ์ด๋„ˆ์™€ ๋‚ด์šฉ ๋ถ„๋ฆฌ

  • ์œ„์น˜์— ์˜์กดํ•˜์ง€ ์•Š๋Š” ์Šคํƒ€์ผ ์ •์˜ :: ๊ตฌ์กฐ์  ์ƒํ™ฉ์— ๊ด€๊ณ„์—†์ด ๋ฌธ์„œ ์–ด๋Š ๊ณณ์—์„œ๋‚˜ ์žฌ์‚ฌ์šฉ ๊ฐ€๋Šฅ.

  • ํƒœ๊ทธ์— ์Šคํƒ€์ผ์„ ์ง€์ •ํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹Œ ํด๋ž˜์Šค๋ช…์„ ๋ถ€์—ฌํ•˜๊ณ  ์Šคํƒ€์ผ์„ ์ง€์ •ํ•œ๋‹ค. :: ํƒœ๊ทธ๊ฐ€ ๋ณ€๊ฒฝ๋˜์–ด๋„ CSS ๋ฐ”๊ฟ€ ํ•„์š” ์—†์Œ.

    <!-- Bad -->
    <h2>...</h2>
    h2 { font-size: 16px }
    
    <!-- Good -->
    <h3 class="subtitle">...</h3>
    <span class="subtitle">...</span>
    .subtitle { font-size: 16px }
    
  • ์–ด๋””์—์„œ๋‚˜ ์žฌ์‚ฌ์šฉ์ด ๊ฐ€๋Šฅํ•œ ํด๋ž˜์Šค ๊ธฐ๋ฐ˜์˜ ๋ชจ๋“ˆ ๊ตฌ์ถ•

 

3) OOCSS Style

๊ธฐ๋ณธ ๊ตฌ์กฐ๊ฐ€ ๋…๋ฆฝ์ ์œผ๋กœ ์ง€์ •๋˜์–ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ํ–ฅํ›„ ๋‹ค๋ฅธ ์ƒ‰์˜ ๋ฒ„ํŠผ์ด ์ถ”๊ฐ€๋˜๋”๋ผ๋„ ์™ธํ˜• ใ…กํƒ€์ผ๋งŒ ์ถ”๊ฐ€๋กœ ์ •์˜ํ•˜๋ฉด ๋œ๋‹ค.

<a href="#" class="btnbase cart">์žฅ๋ฐ”๊ตฌ๋‹ˆ</a>
<a href="#" class="btnbase buy">๋ฐ”๋กœ๊ตฌ๋งค</a>
/* ๋ฒ„ํŠผ ๊ตฌ์กฐ ; ๊ณตํ†ต์ ์ธ ๊ตฌ์กฐ์ง€์ • */
.btnbase {...}

/* ๋ฒ„ํŠผ ์™ธํ˜• */
.cart {...}
.buy {...}

 

 

SMACSS (Scalable and Modular Architecture for CSS)

1) ์Šคํƒ€์ผ์˜ ๋‹ค์„ฏ๊ฐ€์ง€ ์œ ํ˜•

SMACSS๋Š” ์Šคํƒ€์ผ์„ ๋‹ค์„ฏ๊ฐ€์ง€๋กœ ๋ถ„๋ฅ˜, ๊ฐ ์œ ํ˜•์— ๋งž๋Š” ์„ ํƒ์ž(Selector)์™€ ์ž‘๋ช…๋ฒ•(naming convention), ์ฝ”๋”ฉ๊ธฐ๋ฒ•์„ ์ œ์‹œํ•œ๋‹ค.

  1. Base - ๊ธฐ๋ณธ๊ทœ์น™
  2. Layout - ๋ ˆ์ด์•„์›ƒ ๊ทœ์น™
  3. Module - ๋ชจ๋“ˆ ๊ทœ์น™
  4. States - ์ƒํƒœ ๊ทœ์น™
  5. Theme - ํ…Œ๋งˆ ๊ทœ์น™

 

1-1) Base - ๊ธฐ๋ณธ๊ทœ์น™

  • ๊ฐ ๋ธŒ๋ผ์šฐ์ €์˜ ์Šคํƒ€์ผ์„ ์ดˆ๊ธฐํ™” ์‹œํ‚ค๋Š” ๋ชฉ์ ์œผ๋กœ ์‚ฌ์šฉ.
  • ์š”์†Œ(elements) ์Šคํƒ€์ผ์˜ ๊ธฐ๋ณธ๊ฐ’ ์ง€์ • (reset.css , normalize.css)

 

1-2) Layout - ๋ ˆ์ด์•„์›ƒ ๊ทœ์น™

  • ํฐ ํ‹€์˜ ๋ ˆ์ด์•„์›ƒ, ํŽ˜์ด์ง€์˜ ๋‹ค์–‘ํ•œ ์š”์†Œ๋ฅผ ๋ฐฐ์น˜, ๊ตฌ๋ณ„ํ•˜๋Š”๋ฐ ์‚ฌ์šฉ

  • ์ฃผ์š” ์ปดํฌ๋„ŒํŠธ : header, footer, content, aside .. etc

  • ํ•˜์œ„ ์ปดํฌ๋„ŒํŠธ : ์ฃผ์š” ์ปดํฌ๋„ŒํŠธ ๋‚ด์— ์žˆ๋Š” ์ปดํฌ๋„ŒํŠธ (nav, item list, form.. etc)

  • ์ฃผ์š” ์ปดํฌ๋„ŒํŠธ๋Š” id ์…€๋ ‰ํ„ฐ / ํ•˜์œ„ ์ปดํฌ๋„ŒํŠธ๋Š” class ์…€๋ ‰ํ„ฐ๋กœ ์Šคํƒ€์ผ ์ž‘์„ฑ

  • ํด๋ž˜์Šค๋ช…์€ ์ ‘๋‘์‚ฌ๋กœ l- , laylout- ๋ช…์‹œ

    • ex. l-fixed ์œ ๋ฌด์— ๋”ฐ๋ผ ๊ฐ€๋ณ€ํญ์œผ๋กœ ํ• ์ง€ ๊ณ ์ •ํญ์œผ๋กœ ํ• ์ง€ ๊ฒฐ์ •ํ•˜๋Š” ๋ ˆ์ด์•„์›ƒ
#cotent {...}
#aside {...}
.l-fixed #content {...}
.l-fixed #aside {...}

 

1-3) Module - ๋ชจ๋“ˆ ๊ทœ์น™

  • ํŽ˜์ด์ง€์—์„œ ์žฌ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ๊ตฌ์„ฑ์š”์†Œ (๋ฒ„ํŠผ, ์œ„์ ฏ, ๋ฐฐ๋„ˆ.. ๋“ฑ)
  • ๋ชจ๋“ˆ์€ ๋ ˆ์ด์•„์›ƒ ๊ตฌ์„ฑ์š”์†Œ ์•ˆ์— ์กด์žฌํ•˜๋‚˜ ๋‹ค๋ฅธ ๋ชจ๋“ˆ์—์„œ๋„ ์กด์žฌํ•  ์ˆ˜ ์žˆ์Œ
  • ๊ฐ ๋ชจ๋“ˆ์€ ๋…๋ฆฝํ˜•์œผ๋กœ ์กด์žฌํ•˜๋„๋ก ์„ค๊ณ„
  • ์žฌ์‚ฌ์šฉ์„ ์œ„ํ•ด CSS์„ ํƒ์ž๋กœid ํƒœ๊ทธ ์‚ฌ์šฉํ•˜์ง€ ์•Š์Œ
<div class="box">
  <span class="box-name">...</span>
  <span class="box-items">...</span>
</div>
<!-- CSS -->
.box {...}
.box-name {...}
.box-items {...}

 

1-4) State - ์ƒํƒœ ๊ทœ์น™

  • ์š”์†Œ์˜ ์ƒํƒœ๋ณ€ํ™”๋ฅผ ํ‘œํ˜„ํ•˜๋Š” ์Šคํƒ€์ผ
  • ์ฃผ๋กœ JavaScript๋กœ ์กฐ์ž‘๋˜๋Š” ํด๋ž˜์Šค ์ง€์ •
  • ํด๋ž˜์Šค๋ช…์€ ์ ‘๋‘์‚ฌ๋กœ is- ๋“ฑ์„ ๋ช…์‹œ (is-hidden, is-collapsed)
  • ๋ชจ๋“ˆ๊ณผ ๋ ˆ์ด์•„์›ƒ ๋‘˜ ๋‹ค ์ ์šฉ
<!-- ๋ ˆ์ด์•„์›ƒ ์š”์†Œ, ์ ‘ํžŒ ์ƒํƒœ -->
<div id="header" class="is-collapsed">
  <form>
    <!-- ๋ชจ๋“ˆ, ์˜ค๋ฅ˜ ์ƒํƒœ -->
    <div class="msg is-error">
      There is an error!
    </div>
    <!-- ์—ฐ๊ด€๋œ ๋ผ๋ฒจ์ด ์ˆจ๊ฒจ์ง„ ์ƒํƒœ -->
    <label for="search" class="is-hidden">Search</label>
    <input type="text" id="search">
  </form>
</div>

 

1-5) Theme - ํ…Œ๋งˆ ๊ทœ์น™

  • ์‚ฌ์šฉ์ž๊ฐ€ ํ…Œ๋งˆ๋ฅผ ์„ ํƒํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒฝ์šฐ ์‚ฌ์šฉ
  • ์ƒ‰์ƒ, ์ด๋ฏธ์ง€๋ฅผ ๋ถˆ๋ณ€ํ•˜๋Š” ์Šคํƒ€์ผ๊ณผ ๋ถ„๋ฆฌ (background, color, border..)
  • ๋ฉ”์ธ ์Šคํƒ€์ผ ๋’ค์— ์ฝ์–ด ๋“ค์ด๊ฒŒ ํ•˜๊ณ  ๋ฎ์–ด์“ฐ๊ธฐ๋ฅผ ํ•˜๊ฑฐ๋‚˜ ๊ธฐ์กด ์Šคํƒ€์ผ์„ ์žฌ์„ ์–ธํ•˜์—ฌ ์‚ฌ์šฉ
  • theme- ๋“ฑ์˜ ์ ‘๋‘์–ด๋ฅผ ๋ช…์‹œ ๋˜๋Š” theme/ ์™€ ๊ฐ™์€ ๋””๋ ‰ํ† ๋ฆฌ๋กœ ๊ณ„์ธต ๋ถ„๋ฆฌ
  • ์ž์ฃผ ์‚ฌ์šฉ๋˜์ง€๋Š” ์•Š์Œ
/* main.css */
.box { border: 1px solid; }

/* theme.css - main.css ๋’ค์—์„œ ์ฝ๋„๋ก */
.box { border-color: blue; }

 

 


 

Reference

https://velog.io/@yesdoing/BEM-Block-Element-Modifier-Quick-start

https://github.com/hohoya33/css-methodologies

https://chlolisher.tistory.com/11

 

๋ฐ˜์‘ํ˜•