28. 상속과 캐스케이딩

이 글은 부침개, 검은태양님 공역입니다.

소개

Introduction

상속과 캐스케이딩1은 CSS의 기본적인 개념입니다. CSS를 사용하려면 이러한 것을 이해해야 합니다. 다행히 이해하기 어려운 것은 아닙니만, 몇가지 상세한 점은 기억하기 조금 어려울지도 모르겠습니다.

Inheritance and the cascade are two fundamental concepts in CSS .

Everyone who uses CSS needs to understand them.

Fortunately, they aren’t very difficult to grasp, although some of the details may be a bit hard to remember.

두 개념은 밀접하게 연관되어 있지만, 서로 다릅니다. 상속이란 HTML 마크업에서 부모(포함하는) 요소의 속성들을 자식 요소들에게 전달하는 방법과 연관된 것이며, 캐스케이딩이란 서로 다른 CSS 선언들을 문서에 적용하면서도 충돌하지 않게 하는 방법입니다.

The two concepts are closely related, yet different. Inheritance is associated with how the elements in the HTML markup inherit properties from their parent (containing) elements and pass them on to their children, while the cascade has to do with the CSS declarations being applied to a document, and how conflicting rules do or don’t override each other.

이 글에서는 두가지 개념을 자세히 살펴 볼 것입니다. 상속이 좀 더 쉬운 개념이므로 그것을 먼저 보고, 복잡한 캐스케이딩으로 넘어갈 것입니다. 예제에서 사용된 소스코드들 을 다운로드 받아 보십시오. 여기에는 처음에 사용할 HTML 템플릿과 함께, 완성된 CSS 와 HTML 파일들이 압축되어 있습니다.

I will look closely at both concepts in this article. Inheritance is probably an easier concept to grasp, so I’ll start with that, then progress to the intricacies of the cascade. Download the source code for the examples in this article; the zip contains the finished CSS and HTML, as well as the initial HTML template for you to work with as you go through the examples.

이 글의 구조는 다음과 같습니다.

The contents of this article are as follows:

  • 상속
  • Inheritance
    • 상속이 유용한 이유
    • Why inheritance is useful
    • 상속이 동작하는 방법
    • How inheritance works
    • 상속의 예
    • An example of inheritance
    • 강제 상속
    • Forcing inheritance
  • 캐스케이딩
  • The cascade
    • 중요성
    • Importance
    • 특별함
    • Specificity
    • 소스 순서
    • Source order
  • 요약
  • summary
  • 연습문제
  • Exercise questions

상속

Inheritance

CSS에서 상속이란 특정 속성들이 부모 요소로부터 자식 요소로 전달되는 개념입니다. 이것은 유전학에서 말하는 상속과 매우 흡사합니다. 부모의 눈이 파란색이라면, 자식들의 눈 또한 파란색일 확률이 높습니다.

Inheritance in CSS is the mechanism through which certain properties are passed on from a parent element down to its children. It’s quite similar to inheritance in genetics, really.

If the parents have blue eyes, their children will probably have blue eyes, too.

모든 CSS 속성들이 상속되는 것은 아닙니다. 상속된다면 좀 이상한 것들이 있기 때문이죠. 예를 들어, 마진은 상속되지 않습니다. 자식 요소가 부모와 동일한 마진을 가지는 경우는 많지 않기 때문입니다. 대부분의 경우, 상식적으로 생각하면 어떤 속성들이 상속되고 어떤것들이 그렇지 않을 지 쉽게 짐작할 수 있습니다. 좀 더 구체적인 내용을 원한다면, CSS 2.1 명세의 속성 요약 테이블 을 보면 될 것입니다.

Not all CSS properties are inherited, because it doesn’t make sense for some of them to be.

For instance, margins are not inherited, since it’s unlikely that a child element should need the same margins as its parent.

In most cases common sense will tell you which properties are inherited and which aren’t, but to be really sure

you need to look up each property in the CSS 2.1 specification property summary table .

상속이 유용한 이유

Why inheritance is useful

그러면 CSS는 왜 상속이라는 메커니즘을 가지고 있을까요? 가장 쉬운 답안은, 상속이라는 시스템이 없었다면 어땠을지 생각해 보는 것입니다. 상속의 개념이 없었다면 글꼴, 글씨크기, 글색상 같은 것은 모든 요소들에 대해서 전부 각각 지정했어야 했을 것입니다.

Why does CSS have an inheritance mechanism then?

The easiest way to answer that is probably to consider what it’d be like if there was no such thing as inheritance.

You would have to specify things like font family, font size and text colour individually—for every single element type.

html 요소나 body 요소에서 글씨 속성을 정하고 모든 요소들이 그것을 물려받게끔 할 수 있습니다. 특정한 컨테이너 요소에서 배경색과 전경색을 정하면, 그 컨테이너에 들어 있는 모든 자식 요소들이 전경색과 배경색을 물려받습니다. 원래 배경색은 상속되지 않는것이 맞지만 각 요소들의 기본 배경색이 투명하기 때문에 컨테이너가 가진 배경색이 그대로 비쳐 보이는 것입니다. 이 효과는 마치 배경색이 상속되는 것 처럼 보이지만 그렇지는 않습니다. 만약 배경 이미지가 상속된다면 그 결과는 아주 이상할 것입니다.

Using inheritance, you can for example specify the font properties for the html or body elements and they will be inherited by all other elements.
You can specify background and foreground colours for a specific container element and the foreground colour will automatically be inherited by any child elements in that container. The background colour isn’t inherited, but the initial value for background-color is transparent , which means the parent’s background will shine through.
The effect is similar to what you’d get if the background colour were inherited, but consider what would happen if background images were inherited! Every child would have the same background image as its parent and the result would look like a jigsaw puzzle put together by someone with a serious drug problem, since the background would “start over” for each element.

상속의 원리

How inheritance works

HTML의 모든 요소들은 부모로부터 상속할 수 있는 속성은 전부 상속합니다. 유일한 예외라면 html 요소입니다. 부모가 없으니 당연하지요.

Every element in an HTML document will inherit all inheritable properties from its parent except the root element ( html ), which doesn’t have a parent.

물려받은 속성이 적용될지 아닐지는 다른 것들과의 관계에서 설정됩니다. 나중에 캐스케이딩을 다루면서 다시 살펴볼 것입니다. 지금은 그냥, 어머니가 파란 눈을 가졌더라도 아이가 갈색 눈을 가질 수 있는 정도로만 이해하세요.

Whether or not the inherited properties will have any effect depends on other things, as you shall see later on

when I talk about the cascade. Just as a blue-eyed mother can have a brown-eyed child if the father has brown eyes, inherited properties in CSS can be overridden.

상속의 예

An example of inheritance

  1. 다음을 inherit.html 이라는 이름으로 저장해보세요.

    Copy the following HTML document into a new file in your favourite text editor and save it as inherit.html .

    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
    <html lang="en" class="en">
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <title>Inheritance</title>
    </head>
    <body>
    <h1>Heading</h1>
    <p>A paragraph of text.</p>
    </body>
    </html>

    브라우저에서 열어 보면, 브라우저의 기본 스타일이 적용되어서 좀 밋밋해보일 것입니다.

    If you open the document in your web browser you will see a rather boring document displayed according to your browser’s default styling.

  2. 다음을 style.css 라는 이름으로 저장하세요. HTML 파일과 같은 위치에 저장해야 됩니다.

    Create a new empty file in your text editor, copy the CSS rule below into it, and save the file as style.css in the same location as the HTML file.

    html {
    font: 75% Verdana,sans-serif;
    }
  3. HTML 파일의 </head> 태그 앞에 다음 코드를 삽입해서 스타일시트를 링크할 수 있습니다.

    Link the style sheet to your HTML document by inserting the following line before the </head> tag.

    <link rel="stylesheet" type="text/css" href="style.css">
  4. HTML을 저장하고 브라우저에서 다시 열어봅니다. 브라우저의 기본값(보통 Times 또는 Times New Roman)이었던 글꼴이 Verdana 로 바뀌었을 것입니다. 만약 컴퓨터에 그 폰트가 설치되어 있지 않다면 브라우저의 기본값으로 설정된 산세리프체가 보일 것입니다.2

    Save the modified HTML file and reload the document in your browser.
    The font will change from the browser’s default (often Times or Times New Roman) to Verdana.
    If you don’t have Verdana installed on your computer, the text will be displayed in the default sans serif font specified in your browser settings.

    크기도 스타일이 없었을 때의 3/4로 작아졌습니다.

    The text will also become smaller; only three quarters of what it was in the unstyled version.

    스타일시트에서는 단지 html 요소에 대해서만 글꼴을 명시했고 제목이나 문단에 대해서는 지정하지 않았습니다만, 모든 텍스트가 Verdana로, 75% 크기로 보여집니다. 이런 것이 상속입니다.

    The CSS rule we specified applies only to the html element. We didn’t specify any rules for headings or paragraphs, yet all the text now displays in Verdana at 75% of the default size. Why? Because of inheritance.

    font 속성은 단축 속성이며 글씨에 관한 속성들을 한번에 설정할 수 있습니다. 그중에서 두가지 – 크기와 서체만을 명시했지만, 위 선언은 사실 아래와 마찬가지입니다.

    The font property is a shorthand property that sets a whole number of font-related properties.
    We’ve only specified two of them—the font size and the font family—but that rule is equivalent to the following:

    html {
    font-style: normal;
    font-variant: normal;
    font-weight: normal;
    font-size: 75%;
    line-height: normal;
    font-family: Verdana,sans-serif;
    }

    모든 속성들을 물려받으므로, body 요소는 위의 선언들을 html 요소로부터 물려받고, 다시 자신의 자식들 – 제목과 문단으로 넘깁니다.

    All of those properties are inherited, so the body element will inherit them from the html element and then pass them on to its children—the heading and the paragraph.

    글씨 크기에 조금 이상한 점이 있다고 느낄 수 있습니다. html의 글씨 크기가 75% 라고 되어 있는데, 무엇의 75% 라는 것일까요. 그리고 body의 글씨 크기가 부모의 75%이고, 또 제목과 문단은 다시 body의 75%인걸까요?

    But wait a second! There’s something fishy going on with the inheritance of font size, isn’t there? The html element’s font size is set to 75%, but 75% of what ? And shouldn’t the font size of the body be 75% of its parent’s font size, and the font sizes of the heading and the paragraph should be 75% of that of the body element, surely?

    물려받는 것은 공식이 아니라 실제 값입니다. 즉, html은 부모 요소가 없기 떄문에 브라우저에서 정하는 기본값(보통 16픽셀입니다)의 75%를 가집니다. 따라서 12픽셀이 되겠죠. 그리고 body에서 물려받는 것은 “75%” 라는 공식이 아니라, “12픽셀” 이라는 실제 값입니다.

    The value that is inherited is not the specified value —the value we write in our style sheet—but something called the computed value . The computed value is, in the case of font size, an absolute value measured in pixels. For the html element, which doesn’t have a parent element from which to inherit, a percentage value for font size relates to the default font size set in the browser. Most contemporary browsers have a default font size setting of 16px. 75% of 16 is 12, so the computed value for the font size of the html element will probably be 12px. And that is the value that is inherited by body and passed on to the heading and the paragraph.

    (제목의 글씨 크기는 본문보다 더 큽니다. 브라우저들은 대개 이러한 크기 체계를 기본값으로 갖고 있습니다. 나중에 캐스케이딩을 다루면서 더 보게 될 것입니다.)

    (The font size of the heading is larger, because the browser applies some built-in styling of its own. See the discussion about the cascade, below.)

  5. 스타일시트에 두가지를 더 추가합니다.

    Add two more declarations to the rule in your CSS style sheet:

    html {
    font: 75% Verdana,sans-serif;
    background-color: blue;
    color: white;
    }
  6. 이제 배경은 밝은 파란색이고 텍스트는 흰색으로 보입니다. 이 규칙은 html 요소에 적용되었으므로, 문서 전체의 배경이 밝은 파란색입니다. body 요소에서 글씨를 흰색으로 지정한 것을 물려받았고, 다시 자식 요소들에게 물려주고 있습니다. 배경색을 물려받지는 않지만, 모두 투명하므로, 결국 밝은 파란색 배경에 흰 글씨가 보이게 되는 것입니다.

    Now the background is bright blue and all the text is white.
    The rule applies to the html element—the whole document—whose background will be blue.
    The white foreground colour is inherited by the body element and passed on to all children of body —in this case the heading and the paragraph. They don’t inherit the background but it will default to transparent , so the net visual result will be white text on a blue background.

  7. CSS에 한가지 더 추가해봅니다.

    Add another new rule to the style sheet, and save and reload the document:

    h1 {
    font-size: 300%;
    }

    이 규칙은 제목의 글씨 크기를 정합니다. 물려받은 글씨 크기 – 12픽셀에 300%를 적용하므로, 제목의 글씨 크기는 36픽셀이 됩니다.

    This rule sets the font size for the heading. The percentage is applied to the inherited font size—75% of the browser default, which we have assumed to be 12px—so the heading size will be 300% of 12px, or 36px.

강제 상속

Forcing inheritance

inherit 키워드를 써서 기본값으로는 물려받지 않는 속성들도 강제로 물려받게 할 수 있습니다. 사용할 때는 주의해야 하는데, IE 7 이하 버전은 이 키워드를 지원하지 않기 때문입니다.

You can force inheritance—even for properties that aren’t inherited by default—by using the inherit keyword. This should be used with care, however, since Microsoft Internet Explorer (up to and including version 7) doesn’t support this keyword.

다음과 같이 지정하면 모든 문단들이 자신의 부모로부터 배경에 관한 모든 속성들을 물려받게 됩니다.

The following rule will make all paragraphs inherit all background properties from their parents:

p {
background: inherit;
}

단축 속성에도 inherit를 사용할 수 있는데, 이러한 것은 말하자면 모 아니면 도 입니다. 즉, 일부 속성은 물려받고, 일부는 물려받지 않게 할 수는 없다는 것입니다.

With shorthand properties you can use inherit instead of the normal values. You have to use shorthand for everything or nothing—in longhand you can’t specify some values and use inherit for others, because the values can be given in any order and there is no way to specify which values we want to inherit.

상속을 강제하는 일이 자주 있지는 않을겁니다. 뭔가 혼란스러울 때 “취소” 하는 의미로 사용할 수 있고, 값을 계속 쓰는것을 피하기 위해 사용할 수도 있습니다. 다음의 예를 살펴봅시다.

Forcing inheritance isn’t something you need to do every day. It can be useful to “undo” a declaration in a conflicting rule, or to avoid hardcoding certain values. As an example, consider a typical navigation menu:

<ul id="nav">
<li><a href="/">Home</a></li>
<li><a href="/news/">News</a></li>
<li><a href="/products/">Products</a></li>
<li><a href="/services/">Services</a></li>
<li><a href="/about/">About Us</a></li>
</ul>

이것을 가로로 펼쳐진 메뉴로 보여주려면, 다음과 같은 CSS를 쓸 수 있습니다.

To display this list of links as a horizontal menu, you could use the following CSS :

#nav {
background: blue;
color: white;
margin: 0;
padding: 0;
}

#nav li {
display: inline;
margin: 0;
padding: 0 0.5em;
border-right: 1px solid;
}

#nav li a {
color: inherit;
text-decoration: none;
}

#nav 에서 배경색을 파란색으로 정했으니 전체가 그렇게 보입니다. 전경색을 흰색으로 지정한 것을 모든 자식 요소들에서 물려받을 것입니다. 각각의 목록 아이템(#nav li)의 오른쪽 테두리 모양을 정하고 있는데, 색깔은 지정하지 않았습니다. 이렇게 하면 전경색(흰색)을 사용하게 됩니다. 링크들에는 color:inherit 를 지정했으므로 흰색을 물려받게 됩니다.

Here the background colour of the whole list is set to blue in the rule for #nav . This also sets the foreground colour to white, and this is inherited by each list item and each link. The rule for the list items sets a right border, but doesn’t specify the border colour, which means it will use the inherited foreground colour (white). For the links we’ve used color:inherit to force inheritance and override the browser’s default link colour.

물론 테두리와 링크 색깔을 흰색으로 지정할 수도 있지만, 상속을 잘 사용하면 나중에 색상 스키마를 바꾸게 되더라도 하나만 바꾸면 될 수도 있습니다.

Of course I could just as well have specified the border colour as white and the links’ text colour as white, but the beauty of letting inheritance do the job is that you now have only one place to change the colours if you decide to go with another colour scheme.

캐스케이딩

The cascade

CSS 라는 것은 캐스케이딩 스타일시트의 약자입니다. 캐스케이딩이 CSS의 중요 개념이라는 것은 두말할 필요가 없겠지요. 캐스케이딩은 여러가지 선언들을 하나의 요소에 적용하면서 충돌을 피하는 규칙입니다. 여기에는 크게 세가지 범주가 있습니다.

CSS means Cascading Style Sheets, so it shouldn’t come as a surprise that the cascade is an important concept. It’s the mechanism that controls the end result when multiple, conflicting CSS declarations apply to the same element. There are three main concepts that control the order in which CSS declarations are applied:

  1. 중요도
  2. Importance
  3. 명시도
  4. Specificity
  5. 소스 순서
  6. Source order

하나씩 살펴봅시다.

I will look into these concepts below, one by one.

중요도란, 가장… 음.. 중요한 것입니다. 두개의 선언이 같은 중요도를 가진다면, 둘중 명시도가 더 높은 것을 요소에 적용합니다. 두 선언이 명시도마저 똑같다면, 나중에 선언한 것을 요소에 적용합니다.

Importance is most … er … important. If two declarations have the same importance, the specificity of the rules decides which one will apply. If the rules have the same specificity, then source order controls the outcome.

중요도

Importance

CSS 선언의 중요도는, 그것이 “어디” 에서 사용되었는가에 따라 다릅니다. 다음의 순서 대로, 나중 선언이 앞선 선언을 덮어쓰고 요소에 적용됩니다.

The importance of a CSS declaration depends on where it is specified. The conflicting declarations will be applied in the following order; later ones will override earlier ones:

  1. 브라우저 스타일시트
  2. 사용자 스타일시트의 일반 선언
  3. 저작자 스타일시트의 일반 선언
  4. 저작자 스타일시트의 !important
  5. 사용자 스타일시트의 !important
  1. User agent style sheets
  2. Normal declarations in user style sheets
  3. Normal declarations in author style sheets
  4. Important declarations in author style sheets

브라우저 스타일시트는 브라우저에 내장된 스타일시트입니다. 모든 브라우저들이 이러한 것을 가지고 있으며, 사용자 또는 페이지 저자가 선언하지 않은 요소들에 이것을 적용합니다. 예를 들어, 아직 방문하지 않았던 링크는 파란색에 밑줄을 긋습니다.

A user agent style sheet is the built-in style sheet of the browser. Every browser has its default rules for how to display various HTML elements if no style is specified by the user or designer of the page. For instance, unvisited links are usually blue and underlined.

사용자 스타일시트는 사용자가 명시해 둔 스타일시트입니다. 모든 브라우저에서 이걸 지원하지는 않지만, 장애를 가진 사람들에게는 무척이나 유용합니다. 예를 들어, 난독증을 가진 사람은 자신이 읽기 편하게 느끼는 글씨와 색깔을 명시해 둔 스타일시트를 사용하고 싶어할 것입니다.

A user style sheet is a style sheet that the user has specified. Not all browsers support user style sheets, but they can be very useful, especially for users with certain types of disabilities. For instance, a dyslexic person can have a user style sheet that specifies certain fonts and colours that help reading.

오페라에서는 다음과 같은 방법으로 사용자 스타일시트를 지정할 수 있습니다: Tools(맥에서는 Opera 입니다.) > Preferences… > Advanced 탭 > Content 까지 이동한 후 Style Options… 버튼을 누르고, My style sheet 필드에서 사용자 스타일시트를 고르면 됩니다. 원한다면 사용자 스타일시트가 페이지의 그것보다 우선하게 할 수도 있고, 심지어는 사용자 스타일시트와 페이지 지정을 바꿔가면서 쓸 수도 있습니다. 이렇게 하려면 Preferences… 메뉴에서 완전히 빠져 나온 다음, 오페라 브라우저 인터페이스 아무곳에서나 마우스 우클릭, 혹은 컨트롤 키를 누른 상태에서 클릭합니다. 메뉴에서 Customize… > Buttons 탭 > Browser 순으로 이동한 후, Author Mode 버튼을 툴바 아무곳으로나 드래그하면 됩니다.

Opera allows you to specify user stylesheets by going to Tools (or the Opera menu on the Mac) > Preferences… > Advanced tab > Content , clicking on the Style Options… button, then pointing to your user style sheet in the My style sheet text field inside the Display tab of this dialog box. You can also specify if you want the user style sheet to override the author (web designer’s) stylesheet in the Presentation tab, and even add a button into the user interface that allows you to switch between the user and author style sheet. To do this, OK out of the Preferences… menu completely, then right- or Ctrl -click somewhere on the Opera browser interface, select Customize… > Buttons tab > Browser view, and drag the Author Mode button somewhere on to one of your toolbars.

저작자 스타일시트는 우리가 보통 스타일시트라는 표현으로 나타내는 것입니다.

An author style sheet is what we normally refer to when we say “style sheet”. It’s the style sheet that the author of the document (or, more likely, the site’s designer) has written and linked to (or included).

일반 선언은 그냥 일반 선언입니다. 이것의 반대가 중요한 선언입니다. 중요한 선언은 !important 명령이 뒤에 붙습니다.

Normal declarations are just that: normal declarations. The opposite is important declarations , which are declarations followed by an !important directive.

앞에서 보았듯, 중요한 선언들을 다른 모든것보다 우선해서 적용합니다. 예를 들어 난독증이 있는 사용자가 Comic Sans MS 글꼴이 읽기 쉽다고 생각한다면 모든 텍스트가 그 글꼴로 표시되길 바랄 것입니다. 그 사용자는 아래와 같은 사용자 스타일시트를 가지고 있을 수 있습니다.

As you can see, important declarations in a user style sheet will trump everything else, which is logical. That dyslexic user might, for instance, want all text to be displayed in Comic Sans MS if he finds that font easier to read. He could then have a user style sheet containing the following rule:

* {
font-family: "Comic Sans MS" !important;
}

이렇게 하면, 디자이너가 어떻게 스타일시트를 만들었든, 브라우저의 기본 글꼴 설정이 어떻든 관계없이 모든 텍스트가 Comic Sans MS로 나타납니다.

In this case, no matter what the designer specified, and no matter what the browser’s default font family is set to, everything will be displayed in Comic Sans MS.

브라우저는 사용자 스타일시트나 저작자 스타일시트에서 명시하지 않은 요소들에 대해서만 기본값을 적용합니다. 브라우저의 스타일시트가 가장 낮은 우선권을 갖기 때문입니다.

The default browser rendering will only apply if those declarations aren’t overridden by any rules in a user style sheet or an author style sheet, since the user agent style sheet has the lowest precedence.

사이트 디자이너는 스타일시트의 중요도에 대해 고려할 필요는 없습니다. 할 수 있는게 없기 때문이지요. 사용자가 자신만의 스타일시트를 만들어 두었는지 디자이너가 알 방법은 전혀 없습니다. 사용자가 스타일 시트를 만들만한 이유가 있으니 그렇게 하는 것입니다. 그렇긴 하지만 디자이너의 스타일시트보다 우선하는 것이 있다는 걸 모르는 것 보단 낫겠지요.

To be honest, most designers don’t have to think too much about importance, since there’s nothing we can do about it. There is no way we could know if a user has a user style sheet defined that will override our CSS . If they do, they probably have a very good reason for doing so, anyway. Still, it’s good to know what importance is and how it may affect the presentation of our documents.

명시도

Specificity

디자이너들은 명시도에 대해서 잘 이해하고 있어야 합니다. 명시도란 규칙의 선택자가 얼마나 명확하게 요소를 지정하고 있는지 측정한 것입니다. 명시도가 낮은 선택자는 넓은 범위의 요소들에 적용될 것이며, 명시도가 높은 선택자는 페이지의 단 하나의 요소만 선택하고 있을 수도 있습니다.

Specificity is something every CSS author needs to understand and to think about. It can be thought of as a measure of how specific a rule’s selector is. A selector with low specificity may match many elements (like * which matches every element in the document), while a selector with high specificity might only match a single element on a page (like #nav that only matches the element with an id of nav ).

선택자의 명시도는 쉽게 계산할 수 있습니다. 한 요소에 대해서 두개 이상의 선언이 충돌하고 그런 선언들의 중요도가 모두 같다면, 브라우저는 명시도가 가장 높은 선언을 선택합니다.

The specificity of a selector can easily be calculated, as we shall soon see. If two or more declarations conflict for a given element, and all the declarations have the same importance, then the one in the rule with the most specific selector will “win”.

명시도는 네가지 갈래로 계산할 수 있습니다. 이걸 가, 나, 다, 라 라고 합시다. “가” 는 가장 명확한 것이고, “라” 는 가장 모호한 것입니다.

Specificity has four components; let’s call them a, b, c and d. Component “a” is the most distinguishing, “d” the least.

“가” 는 아주 간단합니다. style 속성에서 선언한 것이면 1이고, 그런 선언이 없다면 0 입니다.

Component “a” is quite simple: it’s 1 for a declaration in a style attribute, otherwise it’s 0.

“나” 는 선택자에 들어 있는 id 의 숫자입니다. 선택자에서 id는 #으로 표시합니다.

Component “b” is the number of id selectors in the selector (those that begin with a # ).

“다” 는 선택자에 들어있는 클래스와 가상클래스의 숫자입니다.

Component “c” is the number of attribute selectors—including class selectors—and pseudo-classes.

“라” 는 선택자에 들어 있는 요소와 가상요소의 숫자입니다.

Component “d” is the number of element types and pseudo-elements in the selector.

선택자를 살펴보고 위 갈래에 해당하는 것들을 세어보면 그 규칙에 맞는 명시도를 표현할 수 있습니다. style 속성에 들어 있는 선언에는 선택자가 없으니, 이것의 명시도는 항상 1,0,0,0 입니다.

After a bit of counting, we can thus string those four components together to get the specificity for any rule. CSS declarations in a style attribute don’t have a selector, so their specificity is always 1,0,0,0.

간단한 예제를 살펴봅니다. 이것을 보면 아주 쉽게 이해할 수 있을 것입니다.

Let’s look at a few examples—after this it should be quite clear how this works.

선택자 명시도
h1 1 0,0,0,1
.foo 1 0,0,1,0
#bar 1 0,1,0,0
html>head+body ul#nav *.home a:link 1 2 5 0,1,2,5

마지막 것을 조금 더 자세히 살펴보겠습니다. 이것은 style에 들어 있지 않으므로 가 는 0 입니다. id는 하나(#nav) 있습니다. 따라서 나 는 1 입니다. 클래스 선택자가 하나(.home) 있고, 가상클래스가 하나(:link) 있습니다. 따라서 다 는 2. 마지막으로 요소가 5개(html, head, body, ul, a) 있습니다. 라 는 5 군요. 즉, 명시도는 0,1,2,5 입니다.

Let’s look at the last example in some more detail. You get a=0 since it’s a selector, not a declaration in a style attribute. There is one ID selector ( #nav ), so b=1. There is one attribute selector ( .home ) and one pseudo-class ( :link ), so c=2. There are five element types ( html , head , body , ul and a ), so d=5. The final specificity is thus 0,1,2,5.

선택자 조합을 나타내는 기호들(>, +, 공백 등)은 선택자의 명시도에는 영향을 끼치지 않습니다. 전체 선택자인 * 역시 명시도에는 영향을 미치지 않습니다.

It’s worth noting that combinators (like > , + and the white space) do not affect a selector’s specificity. The universal selector ( * ) has no input on specificity, either.

한가지 더 알아두어야 하는 것은, id를 id로 사용하는 것과 속성으로서 사용하는 것은 무척 다르다는 것입니다. 같은 요소를 지칭하지만, #nav 의 명시도는 0,1,0,0 이고 [id=”nav”] 의 명시도는 0,0,1,0 입니다.

Also worth noting is that there is a huge difference in specificity between an id selector and an attribute selector that happens to refer to an id attribute. Although they match the same element, they have very different specificities. The specificity of #nav is 0,1,0,0 while the specificity of [id="nav"] is only 0,0,1,0.

실제 예제를 살펴봅시다.

Let’s look at how this works in practice.

  1. HTML 문서에 문단을 하나 추가합니다.

    Start by adding another paragraph to your HTML document.

    <body>
    <h1>Heading</h1>
    <p>A paragraph of text.</p>
    <p>A second paragraph of text.</p>
    </body>
  2. 문단의 텍스트는 다른 색깔을 갖도록 CSS를 수정합니다.

    Add a rule to your style sheet to make text in paragraphs have a different colour:

    p {
    color: cyan;
    }
  3. 두 파일을 저장하고 브라우저에서 열어봅니다. 이제 두 문단의 텍스트는 모두 푸르스름하게 보입니다.

    Save both files and reload the document in your browser, and there should now be two paragraphs with cyan text.

  4. 첫번째 문단에 id 속성을 넣어서, CSS에서 가리킬 수 있도록 합니다.

    Set an id on the first paragraph, so you can target it easily with a CSS selector.

    <body>
    <h1>Heading</h1>
    <p
    id="special">A paragraph of text.</p>
    <p>A second paragraph of text.</p>
    </body>
  5. special 문단에 대한 CSS 속성을 적용합니다.

    Add a rule for the special paragraph in your style sheet:

    #special {
    background-color: red;
    color: yellow;
    }
  6. 조금 더 다양한 색깔을 갖게 되었습니다.

    Save both files and reload the document in your browser to see the now rather colourful result.

두 문단에 적용된 선언들을 살펴봅시다.

Let’s look at the declarations that apply to your two paragraphs.

첫번째 선언을 통해 “모든” 문단들에 color:cyan 을 적용했습니다. 두번째 선언을 통해 빨간 배경색과 노란색 전경색을 적용했습니다. 두번째 선언은 special 이라는 id를 가진 단 하나의 요소에만 적용됩니다. 첫번째 문단은 두가지 선언 모두에 들어맞습니다. 문단이기도 하고, special 이라는 id를 갖고 있기도 합니다.

The first rule you added sets color:cyan for all paragraphs. The second rule sets a red background colour and sets color:yellow for the single element that has the id of special . Your first paragraph matches both of those rules; it is a paragraph and it has the id of special .

빨간색 배경은 어려울 것이 없습니다. #special 에만 적용되는 거니까요. 두 선언 모두가 전경색 속성을 설정하고 있으므로, 충돌이 생길 수 있습니다. 이 두 선언은 같은 스타일시트에서 선언되었고 둘 다 일반 선언이므로, 모두 같은 중요도를 갖습니다. 따라서 어떤것을 적용할지 판단하려면 명시도를 계산해봐야 합니다.

The red background isn’t a problem, because it’s only specified for #special . Both rules contain a declaration of the color property, though, which means there is a conflict. Both rules have the same importance—they are normal declarations in the author style sheet—so you have to look at the specificity of the two selectors.

첫번째 선언의 선택자는 p 입니다. 명시도는 0,0,0,1 이죠. 두번째 선언의 선택자 #special 는 id 를 사용하고 있으니 명시도가 0,1,0,0 입니다. 두번째 선언의 명시도가 첫번째 것보다 높으므로, 전경색을 노란색으로 지정하게 됩니다.

The selector of the first rule is p , which has a specificity of 0,0,0,1 according to the rules above since it contains a single element type. The selector of the second rule is #special , which has a specificity of 0,1,0,0 since it consists of an id selector. 0,1,0,0 is much more specific than 0,0,0,1 so the color:yellow declaration wins and you get yellow text on a red background.

소스 순서

Source order

하나의 요소를 가리키는 선언이 두개 있고, 두 선언의 중요도와 명시도가 모두 같다면, 기댈 수 있는 근거는 이제 순서 밖에는 남지 않았습니다. 이런 경우에는 나중에 나온 선언을 선택하게 됩니다.

If two declarations affect the same element, have the same importance and the same specificity, the final distinguishing mark is the source order . The declaration that appears later in the style sheets will “win” over those that come before it.

외부 스타일시트 파일 하나만 사용한다면, 충돌이 있을 경우 그 파일에서 가장 아래쪽에 선언된 것을 선택합니다. 스타일시트 파일을 여러개 사용하는 경우도 있을 텐데, 이런 경우는 HTML에서 스타일시트를 호출하는 순서를 적용합니다. 즉, 마지막에 불러온 스타일시트에 있는 선언이, 위에서 불러온 스타일시트의 선언을 덮어쓰는 것입니다. 실제 예제를 봅시다.

If you have a single, external style sheet, then the declarations at the end of the file will override those that occur earlier in the file if there’s a conflict. The conflicting declarations could also occur in different style sheets. In that case, the order in which the style sheets are linked, included or imported controls which declaration will be applied, so if you have two linked stylesheets in a document head , the one linked to last will override the one linked to first. Let’s look at a practical example of how this works.

  1. 스타일시트의 마지막에 다음과 같은 내용을 추가합니다.

    Add a new rule to your style sheet, at the very end of the file, like so:

    p {
    background-color: yellow;
    color: black;
    }
  2. 페이지를 확인해봅니다. 모든 문단에 적용되는 선언이 2개 있습니다. 두가지 선언은 중요도와 명시도가 모두 같으니까, 순서상 마지막에 있는 선언을 쓰게 됩니다.

    Save and reload the web page. you now have two rules that match all paragraphs. They have the same importance and the same specificity (since the selector is the same), therefore the final mechanism for disambiguating will be the source order.

    마지막 선언에서는 전경색에 검은색을 지정하고 있는데, 이렇게 하면 앞에서 지정한 푸르스름한 색을 덮어씁니다.

    The last rule specifies color:black and that will override color:cyan from the earlier rule.

첫번째 문단은 지금 지정한 선언에 전혀 영향받지 않았음을 유념해야 합니다. 지금 지정한 선언이 마지막에 있지만, #special 의 선언보다 명시도가 낮습니다. 명시도가 순서보다 우선한다는 것을 명확하게 보여주는 예 입니다.

Note how the first paragraph isn’t affected at all by this new rule. Although the new rule appears last, its selector has lower specificity than the one for #special . This shows clearly how specificity trumps source order.

요약

Summary

웹 디자이너라면 상속과 캐스케이딩이라는 기본적인 개념을 반드시 이해해야 합니다.

Inheritance and the cascade are fundamental concepts that every web designer needs to understand.

상속을 통해서, 상위의 요소에 지정한 속성들을 모든 자손 요소들에게 물려줄 수 있습니다. 기본값으로 상속되는 속성은 일부분이지만, inherit 키워드를 사용하면 강제로 물려받게끔 할 수 있습니다.

Inheritance lets us declare properties on high-level elements and allows those properties to trickle down to all descendant elements. Only some properties are inherited by default, but inheritance can be forced with the inherit keyword.

캐스케이딩은 서로 충돌하는 선언들을 정리해줍니다. 중요한 선언이 덜 중요한 선언을 덮어 쓰고, 중요도가 같은 선언 중에서는 명시도가 높은 선언에 우선권이 있습니다. 전부 다 같다면, 순서상 마지막에 있는 것을 선택합니다.

The cascade sorts out all conflicts when multiple declarations would affect a given element. Important declarations will override less important ones. Among declarations with equal importance, the rule’s specificity controls which one will apply. And, all else being equal, the source order makes the final distinction.

연습문제

Exercise Questions

  • width 속성은 상속되는 속성일까요? 부모 요소의 너비를 물려받는 것이 상식에 맞는지 먼저 생각해 본 다음, CSS 명세 에서 정답을 찾아보세요.
  • Is the width property inherited? Think about it first—would it make sense?—then look up the correct answer in the CSS specification .
  • 예제 스타일시트 의 마지막에 color:black !important 선언을 추가한다면, id가 “special”인 문단의 모양이 바뀔까요?
  • If we add !important to the color:black declaration in the last rule in our example style sheet , will this have any effect on the text colour in the first, “special” paragraph?
  • #special 과 html>head+body>h1+p 중 어떤 것이 더 명시도가 높을까요?
  • Which selector is more specific, ” #special ” or ” html>head+body>h1+p “?
  • 페이지 저작자의 의도와 상관 없이 예제 문서를 검은색 Comic Sans MS로 표시하려면 어떤 사용자 스타일시트를 만들어야 할까요?
  • What should a user style sheet look like to make our test document display in black Comic Sans MS on a whitebackground, regardless of the author style sheet?

저자

About the author

Tommy Olsson 은 스톡홀름 근처에 살고 있는 웹 표준과 접근성 전도사입니다. Tommy Olsson 은 1993년에 처음으로 HTML 문서를 작성했으며, 현재는 스웨덴 정부 기관에서 웹마스터로 일하고 있습니다.

Tommy Olsson is a pragmatic evangelist for web standards and accessibility, who lives in the outback of central Sweden. He wrote his first HTML document in 1993 and is currently the technical webmaster for a Swedish government agency.

Paul O’Brien 과 함께 The Ultimate CSS Reference 이라는 꽤 유명한 책도 썼고, The Autistic Cuckoo 라는 블로그도 운영하고 있었지만 요즘은 거의 버려두고 있는 모양입니다.

He has written one book so far—The Ultimate CSS Reference (with Paul O’Brien)—and has a sadly neglected blog called The Autistic Cuckoo .

  1. 역주:단계적 상속이라고 합니다. 상속Inheriance과 혼동되는 것을 막기 위해 캐스케이딩이라고 옮겨 적었습니다.
  2. 역주: 여기서 산세리프는 특정한 글꼴이 아니라 대표 글꼴입니다.
이 글과 비슷한 종류의 글은 'CSS' 카테고리에서 더 찾아볼 수 있습니다. 또한, , 태그로도 검색해 보실 수 있습니다. 북마크를 하시려면 퍼머 링크로 기억해 주세요.
이 글을 다 읽어주셨다면, 댓글을 남겨주세요. 좋았다라는 격려도 좋고, 잘못된 부분을 지적해 주시는 것도 좋습니다. 마음에 드셨다면 아래 Like 버튼을 눌러서 페이스북과 트위터로 소개해 주시면 더욱 좋겠습니다.