BEM์ด๋ Block, Element, Modifier์ ์ฒซ ๊ธ์๋ง ๊ฐ์ ธ์ ์ด๋ฆ ์ง์ Component ๊ธฐ๋ฐ์ ์น ๊ฐ๋ฐ ์ ๊ทผ๋ฒ ์ค ํ๋ ์ ๋๋ค.
์ด ๋ฐฉ๋ฒ๋ก ์ ์ ์ ์ธํฐํ์ด์ค๋ฅผ ๋ ๋ฆฝ๋ ์ฌ๋ฌ ๊ฐ์ ๋ธ๋ก์ผ๋ก ๋ถ๋ฆฌํ์๋ ๊ฒ์ด ๋ชฉํ์ ๋๋ค. ์ด๊ฒ์ ๋ณต์กํ UI๋ฅผ ๊ฐ์ง ํ์ด์ง์ ์ธํฐํ์ด์ค ๊ฐ๋ฐ ํ๊ฒฝ์ ์ฝ๊ณ ๋น ๋ฅด๊ฒ ํ๋ฉฐ, Copy and Paste ์์ด ์กด์ฌํ๋ ์ฝ๋์ ์ฌํ์ฉ์ ๊ฐ๋ฅํ๊ฒ ํฉ๋๋ค.
๊ธฐ๋ฅ์ ์ผ๋ก ๋ ๋ฆฝ๋ ํ์ด์ง์ Component๋ ์ฌ์ฌ์ฉ ๋ ์ ์์ด์ผ ํฉ๋๋ค. HTML์์ ๋ธ๋ก๋ค์ class ์์ฑ์ผ๋ก ํํ๋ฉ๋๋ค.
์๋๋ Block์ ํน์ง๋ค ์ ๋๋ค.
<!-- ์์ -->
<!-- ์ณ์ ์, ์๋ฌ ๋ธ๋ก์ด ์๋ฏธ์ ์ ์ ํฉ๋๋ค. -->
<div class="error"></div>
<!-- ํ๋ฆฐ ์, ๋ธ๋ก์ ์ด๋ป๊ฒ ํํ๋์ด์ง๋ ์ง๋ฅผ ๋ํ๋ด์ง ์์ต๋๋ค. -->
<div class="red-text"></div>
์ด๋ฐ ํน์ง๋ค์ด ๋ธ๋ก์ ์ฌ์ฌ์ฉ์ฑ์ด๋ ๋ธ๋ก์ด ์์ง์ผ ๋ ํ์ํ ๋ ๋ฆฝ์ฑ์ ๋ณด์ฅํฉ๋๋ค.
<!-- `header` block -->
<header class="header">
<!-- Nested `logo` block -->
<div class="logo"></div>
<!-- Nested `search-form` block -->
<form class="search-form"></form>
</header>
๋ธ๋ก์์ ๋ถ๋ฆฌ๋์ด ์ฌ์ฉ๋ ์ ์๋ ํ ๋ธ๋ก์ ์ด๋ฃจ๋ ๋ถ๋ถ ์ ๋๋ค.
์๋๋ Element์ ํน์ง๋ค ์ ๋๋ค.
block-name__element-name
์
๋๋ค. element ์ด๋ฆ์ double underscore(__
)๋ฅผ ์ฌ์ฉํด์ ๋ธ๋ก ์ด๋ฆ์ผ๋ก๋ถํฐ ๋ถ๋ฆฌ๋์ด์ผ ํฉ๋๋ค. <!-- Example -->
<!-- `search-form` block -->
<form class="search-form">
<!-- `input` element in the `search-form` block -->
<input class="search-form__input">
<!-- `button` element in the `search-form` block -->
<button class="search-form__button">Search</button>
</form>
block__elem1__elem2
) <!--
์ณ์ ์. element์ ์ด๋ฆ ๊ตฌ์กฐ๊ฐ ์๋์ ํจํด์ ๋ฐ๋ฅด๊ณ ์์ต๋๋ค.
`block-name__element-name`
-->
<form class="search-form">
<div class="search-form__content">
<input class="search-form__input">
<button class="search-form__button">Search</button>
</div>
</form>
<!--
ํ๋ฆฐ ์. element์ ์ด๋ฆ ๊ตฌ์กฐ๊ฐ ์๋์ ํจํด์ ๋ฐ๋ฅด์ง ์์ต๋๋ค.
`block-name__element-name`
-->
<form class="search-form">
<div class="search-form__content">
<!-- Recommended: `search-form__input` or `search-form__content-input` -->
<input class="search-form__content__input">
<!-- Recommended: `search-form__button` or `search-form__content-button` -->
<button class="search-form__content__button">Search</button>
</div>
</form>
๋ธ๋ก ์ด๋ฆ์ namespace๋ก ์ ์ํฉ๋๋ค. ์ด namespace๋ element๋ค์๊ฒ block์ ์์กดํ๊ณ ์๋ ๊ฒ์ ๋ณด์ฅํฉ๋๋ค. (block__elem
)
ํ ๋ธ๋ก์ DOM tree์์ ์ฌ๋ฌ ๊ฐ๋ก ์ค์ฒฉ๋ element๋ค์ ๊ฐ์ง ์ ์์ต๋๋ค.
Example
<div class="block">
<div class="block__elem1">
<div class="block__elem2">
<div class="block__elem3"></div>
</div>
</div>
</div>
๊ทธ๋ฌ๋, ์ด ๋ธ๋ก ๊ตฌ์กฐ๋ BEM ๋ฐฉ๋ฒ๋ก ์์ element ๋ค์ ๋ชฉ๋ก๋ค๋ก์ ํํ๋์ด ์ง๋๋ค.
Example
.block {}
.block__elem1 {}
.block__elem2 {}
.block__elem3 {}
์ด๊ฒ์ ๊ฐ๊ฐ์ ๋ถ๋ฆฌ๋ element์ ๋ํด ์ฝ๋์ ๋ณํ์์ด ๋ธ๋ก์ DOM ๊ตฌ์กฐ๋ฅผ ๋ณํ์ํค๋ ๊ฒ์ ํ๋ฝํฉ๋๋ค.
Example
<div class="block">
<div class="block__elem1">
<div class="block__elem2"></div>
</div>
<div class="block__elem3"></div>
</div>
๋ธ๋ก ๊ตฌ์กฐ๊ฐ ๋ณํ๋๋๋ผ๋ element๋ค์ ๊ท์น๊ณผ ๊ทธ๋ค์ ์ด๋ฆ์ ๋๊ฐ์ด ์ ์ง๋์ด์ผ ํฉ๋๋ค.
ํ element๋ ํญ์ ํ ๋ธ๋ก์ ๋ถ๋ถ์ด์ด์ผ ํ๋ฉฐ, ๋ธ๋ก์ผ๋ก๋ถํฐ ๋ถ๋ฆฌ๋์ด ์ฌ์ฉ๋ ์ ์์ต๋๋ค.
Example
<!-- ์ณ์ ์. element๋ค์ the `search-form` block ๋ด๋ถ์ ์์นํ๊ณ ์์ต๋๋ค. -->
<!-- `search-form` block -->
<form class="search-form">
<!-- `input` element in the `search-form` block -->
<input class="search-form__input">
<!-- `button` element in the `search-form` block -->
<button class="search-form__button">Search</button>
</form>
<!--
ํ๋ฆฐ ์. element๋ค์ด the `search-form` block ์ ๋ฐ์ ์์นํ๊ณ ์์ต๋๋ค.
-->
<!-- `search-form` block -->
<form class="search-form">
</form>
<!-- `input` element in the `search-form` block -->
<input class="search-form__input">
<!-- `button` element in the `search-form` block-->
<button class="search-form__button">Search</button>
element๋ block component์์ ์ ํ์ฌํญ์ ๋๋ค. ๋ชจ๋ block ๋ค์ด element๋ฅผ ๊ฐ์ง์ง ์์ต๋๋ค.
Example
<!-- `search-form` block -->
<div class="search-form">
<!-- `input` block -->
<input class="input">
<!-- `button` block -->
<button class="button">Search</button>
</div>
๋ง์ฝ ์ฝ๋์ ํ ๋ถ๋ถ์ด ์ฌ์ฌ์ฉ ๋์ด ์ง๊ณ , ๊ทธ ๋ถ๋ถ์ด ๊ตฌํ๋ ๋ค๋ฅธ ํ์ด์ง์ ์ปดํฌ๋ํธ๋ค์ ์์กดํ์ง ์๋๋ค๋ฉด Block์ผ๋ก ๋ง๋ค ์ ์์ต๋๋ค.
์ฝ๋์ ํ ๋ถ๋ถ์ด ๋ถ๋ชจ entity(the block) ์์ด ๋ถ๋ฆฌ๋์ด ์ฌ์ฉ๋์ด ์ง ์ ์๋ค๋ฉด element๋ก ๋ง๋ค ์ ์์ต๋๋ค.
ํ์ง๋ง ๊ฐ์ํํ ๊ฐ๋ฐ์ ์ํ์ฌ ์์ ๋ถ๋ถ๋ค๋ก ๋ถ๋ฆฌ๋์ด์ผ ํ๋ element๋ค์ ์์ธ์ ๋๋ค. BEM ๋ฐฉ๋ฒ๋ก ์์ element ๋ค์ element ๋ค์ ๋ง๋ค ์ ์์ต๋๋ค. ์ด์ ๊ฐ์ ๊ฒฝ์ฐ, element๋ฅผ ๋ง๋๋ ๊ฒ ๋์ ์ service ๋ธ๋ก์ ๋ง๋ค์ด์ผ ํฉ๋๋ค.
block์ด๋ element์ ํ๋์ด๋ ์ํ, ์ธ์์ ์ ์ํ๋ entity ์ ๋๋ค.
์๋๋ Modifier์ ํน์ง๋ค ์ ๋๋ค.
size_s
or theme_islands
disabled
or focused
directions_left-top
_
)๋ก ๋ถ๋ฆฌ๋์ด์ผ ํฉ๋๋ค.disabled
. ๋ง์ฝ Boolean modifier๊ฐ ๋ํ๋๋ค๋ฉด ๊ทธ ๊ฐ์ true
๋ก ์ถ์ธก๋์ด ์ง ๊ฒ๋๋ค.block-name_modifier-name
block-name__element-name_modifier-name
Example
<!-- The `search-form` block ์ `focused` Boolean modifier๋ฅผ ๊ฐ์ง๋๋ค. -->
<form class="search-form search-form_focused">
<input class="search-form__input">
<!-- The `button` element ๋ `disabled` Boolean modifier ๋ฅผ ๊ฐ์ง๋๋ค.-->
<button class="search-form__button search-form__button_disabled">Search</button>
</form>
islands
๋์์ธ ํ
๋ง๋ฅผ ๊ฐ์ง ๋ฉ๋ด" : menu_theme_islands
block-name_modifier-name_modifier-value
block-name__element-name_modifier-name_modifier-value
Example
<!-- The `search-form` block ์ the value `islands`๋ฅผ ๊ฐ์ง `theme` modifier๋ฅผ ๊ฐ์ง๋๋ค. -->
<form class="search-form search-form_theme_islands">
<input class="search-form__input">
<!-- The `button` element has the `size` modifier with the value `m` -->
<button class="search-form__button search-form__button_size_m">Search</button>
</form>
<!-- two identical modifiers๋ different values ์ํฉ์ ์ผ๋ก ๊ฐ์ง๋๋ค. -->
<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>
๋จ์ผ DOM node์์ ๋ค๋ฅธ BEM entity๋ค์ ์ฌ์ฉํ๊ธฐ ์ํ ๊ธฐ์
์๋์ ๊ฐ์ด ํผํฉํ ์ ์์ต๋๋ค.
Example
<!-- `header` block -->
<div class="header">
<!--
`search-form` block ์ the `header` block์ `search-form` element ์
๊ฐ์ด ์ฌ์ฉ๋์ด ์ง๋๋ค.
-->
<div class="search-form header__search-form"></div>
</div>
์ ์์ ์์ ํ๋(behavior)๊ณผ search-form
block์ ์คํ์ผ๊ณผ header
block ์ search-form
element ์ ์คํ์ผ์ ๊ฒฐํฉํ์ต๋๋ค. ์ด๋ฐ ์ ๊ทผ์ search-form
block์ด ์ผ๋ฐ์ ์ผ๋ก ์ ์ง๋๋ ๋์, header__search-form
element์ ์์น์ margin๊ฐ์ ์ค์ ํ ์ ์์ต๋๋ค. ๊ฒฐ๊ณผ์ ์ผ๋ก, ์ฐ๋ฆฌ๋ ์ด๋ค padding๊ฐ๋ ์ ์ํ์ง ์๊ธฐ ๋๋ฌธ์ ๋ชจ๋ ํ๊ฒฝ์์๋ block์ ์ฌ์ฉํ ์ ์์ต๋๋ค. ์ด๊ฒ์ด ์ฐ๋ฆฌ๊ฐ ๋
๋ฆฝ์ ์ด๋ผ๊ณ ๋ถ๋ฅผ ์ ์๋ ์ด์ ์
๋๋ค.
BEM ๋ฐฉ๋ฒ๋ก ์์ ์ฑํ ๋ ์ปดํฌ๋ํธ ์ ๊ทผ๋ฒ์ ๋ํ ํ๋ก์ ํธ์ ํ์ผ๊ตฌ์กฐ์๋ ์ ์ฉ๋ฉ๋๋ค. block๊ณผ element, modifier์ ๊ตฌํ์ ๋ ๋ฆฝ์ ์ธ ๊ธฐ์ ํ์ผ๋ค๋ก ๋ถ๋ฆฌ๋๋ฉฐ, ์ด ๋ถ๋ฆฌ๋ ํ์ผ๋ค์ ๊ฐ๊ฐ ๋ฐ๋ก ์ฐ๊ฒฐํ ์ ์์ต๋๋ค.
File structure์ ์๋์ ํน์ฑ์ ์ง๋๋๋ค.
header
block์ header/
directory์์, ์๊ณ menu
block์ menu/
directory ์์ ์๋ค.header.css
์ header.js
๋ก ๊ตฌ์ฑ๋๋ค.__
)๋ก ์์ํ๋ค. ์๋ฅผ ๋ค์ด, header/__logo
๋ menu/__item/
๊ณผ ๊ฐ๋ค._
)๋ก ์์ํ๋ค. ์๋ฅผ ๋ค์ด, header/_fixed/
์ menu/_theme_islands/
์ ๊ฐ๋ค.header__input.js
์ header_theme_islands.css
์ ๊ฐ๋ค.Example
search-form/ # Directory of the search-form
__input/ # Subdirectory of the search-form__input
search-form__input.css # CSS implementation of the
# search-form__input element
search-form__input.js # JavaScript implementation of the
# search-form__input element
__button/ # Subdirectory of the search-form__button
# element
search-form__button.css
search-form__button.js
_theme/ # Subdirectory of the search-form_theme
# modifier
search-form_theme_islands.css # CSS implementation of the search-form block
# that has the theme modifier with the value
# islands
search-form_theme_lite.css # CSS implementation of the search-form block
# that has the theme modifier with the value
# lite
search-form.css # CSS implementation of the search-form block
search-form.js # JavaScript implementation of the
# search-form block
์์ ๊ฐ์ ํ์ผ ๊ตฌ์กฐ๋ ์ฝ๋์ ์ฌ์ฌ์ฉ์ฑ์ ๋์ ๋๋ค.
์์ ํ์ผ ๊ตฌ์กฐ๋ ์ถ์ฒ ์ฌํญ์ด์ง ํ์ ์ฌํญ์ด ์๋๋ฉฐ, ๋ค๋ฅธ ๋์์ ํ๋ก์ ํธ ๊ตฌ์กฐ๋ฅผ ์ฌ์ฉ ํ ์ ์์ต๋๋ค. ๋ํ, ํ์ผ์ ๊ตฌ์ฑํ๊ธฐ ์ํ BEM ์์น์ ๋ฐ๋ฅด๊ธฐ๋ง ํด๋ ๋ฉ๋๋ค.
์๋ฌธ : BEM Quick start
์์ง์ ๋ด์ฉ ๊ณต์ ๊ฐ์ฌํฉ๋๋ค. :)