CSS 基礎 Part1:Selector


Posted by saffran on 2021-02-06

CSS 的全名是 Cascading Style Sheets (階層式樣式表)

同時符合多個條件的 CSS Selector

把 selector 連在一起寫,就代表要「同時符合這些條件」才可以

範例一

html:
現在,第一個 div 和 span 都有 class="bg-green"
但是,我只想選到「同時符合又是 div 又是 class="bg-green"」的元素,該怎麼寫 css 的 selector 呢?

    <div class="bg-green">
      hello1
    </div>
    <div>
      hello2
    </div>
    <span class="bg-green">
      hello3
    </span>

css:
選到「同時符合又是 div 又是 class="bg-green"」的元素

div.bg-green{
  background-color: green;
}

範例二

html:
現在,我只想選到「同時具有 bg-greenbg-real-green 這兩個 class」的元素,該怎麼寫 css 的 selector 呢?

    <div class="bg-green bg-real-green">
      hello1
    </div>
    <div>
      hello2
    </div>
    <div class="bg-green">
      hello3
    </div>

css:
選到「同時具有 bg-greenbg-real-green 這兩個 class」的元素

.bg-green.bg-real-green{
  background-color: green;
}

選擇底下的元素

html:

    <div class="levelOne">
      lv1
      <div>
        lv2
        <div>lv3</div>
        <div>hello</div>
      </div>
    </div>

> 只會選到「.levelOne 的下一層」

css:
就會選到 lv2

.levelOne > div {
  background-color: salmon;
}

> 只會選到「.levelOne 的再下一層」

css:
因為第三層有兩個 div,因此這兩個 div 都會被選到,因為這兩個 div 都是在 lv2 的下一層

.levelOne > div > div{
  background-color: salmon;
}

不用 > 就會選到「.levelOne 底下所有的 .bg-green

html:

    <div class="levelOne">
      lv1
      <div>
        lv2
        <div class="bg-green">lv3</div>
      </div>
      <div class="bg-green">hello</div>
    </div>

不使用 >,就可以選到 .levelOne 底下所有的 .bg-green(不管是在第幾層,都會被選到)

.levelOne .bg-green{
  background-color: green;
}

CSS Selector:~ 與 +

+ 選到「同一層裡面,右邊那一個符合條件的元素」(一定要相鄰)

在同一層中,「旁邊」指的就是「上下相鄰」的意思

規則:會被選到的只有 + 右邊的那個,+ 左邊的不會被選到

範例一

html:

    <div class="bg-red">div1</div>
    <div>div2</div>
    <div class="bg-red">div3</div>
    <div class="bg-red">div4</div>

css:
這樣,會選到「.bg-red 右邊的那一個 .bg-red」,也就是 <div class="bg-red">div4</div>

.bg-red + .bg-red {
  background-color: red
}

範例二

html:

    <div>123</div>
    <span>456</span>
    <span>7899</span>

css:
+ 只會選到 div 右邊的那一個 span,因此就只會選到 <span>456</span> 而已

div + span {
  background-color: lightgreen;
}

~ 選到「同一層裡面,右邊所有符合條件的元素」(不一定要相鄰)

規則:會被選到的只有 ~ 右邊的元素,~ 左邊的不會被選到

html:

    <div>123</div>
    <span>456</span>
    <span>7899</span>

css:
~ 可以選到「div 右邊所有的 span」

div ~ span {
  background-color: lightgreen;
}

+~ 的使用時機

範例一:讓元素中間有間距

html:

    <span class="bg-red">span1</span>
    <span class="bg-red">span2</span>
    <span class="bg-red">span3</span>
    <span class="bg-red">span4</span>

在做 navbar 的選項時,會希望:
最左邊沒有 margin,但是在每個元素中間有間距
因此,我只想要選到「後面三個元素」去套用 margin-left: 20px
css:

.bg-red ~ .bg-red {
  background-color: red;
  margin-left: 20px;
}

CSS Selector:Pseudo-classes,以 hover 為例

Pseudo-classes 就是「假的 class」,是瀏覽器幫我加上去的一個 class,可以選到「元素在某個狀態下的樣子」

除了 :hover 之外,還有其他很多的 Pseudo-classes

CSS Selector:nth-child

nth-child 也是一種 Pseudo-class,可以幫我選到「這一層裡面的第 n 個子元素」

:first-child

html:

    <div class="wrapper">
      <div>row1</div>
      <div>row2</div>
      <div>row3</div>
      <div>row4</div>
      <div>row5</div>
    </div>

css:
:first-child 就可以只選到「.wrapper 這一層裡面的第一個子元素,且要是 div」

.wrapper div:first-child {
  background-color: salmon
}

:last-child

css:
:last-child 就可以只選到「.wrapper 這一層裡面的最後一個子元素,且要是 div」

.wrapper div:last-child {
  background-color: salmon
}

:nth-child(3)

css:
:nth-child(3) 就可以只選到「.wrapper 這一層裡面的第三個子元素,且要是 div」

會先看 :nth-child(3) (是否為這一層裡面的第三個子元素),然後才看是否為 div

.wrapper div:nth-child(3) {
  background-color: salmon
}

:nth-child(odd)

css:
:nth-child(odd) 就可以只選到「.wrapper 這一層裡面,被放在奇數列的子元素,且要是 div」

會先看 :nth-child(odd)(是否為這一層裡面的奇數列的子元素),然後才看是否為 div

.wrapper div:nth-child(odd) {
  background-color: salmon
}

:nth-child(3n)

html:

    <div class="wrapper">
      <div>row1</div>
      <div>row2</div>
      <div>row3</div>
      <div>row4</div>
      <div>row5</div>
      <div>row6</div>
      <div>row7</div>
      <div>row8</div>
      <div>row9</div>
    </div>

css:
這裡的 (3n),n 會帶入 0, 1, 2, 3, 4...
所以,第 0, 3, 6, 9 個子元素且是 div 的就會被選到

.wrapper div:nth-child(3n) {
  background-color: green;
}

:nth-child(4n+1)

小括弧內可以填入任何的運算

:nth-child() 會先看元素的順序

現在,我想要選到「.wrapper 這一層裡面的第二個 .bg-green
html:

    <div class="wrapper">
      <div class="bg-green">row1</div>
      <div>row2</div>
      <div class="bg-green">row3</div>
      <div>row4</div>
      <div>row5</div>
    </div>

css 錯誤寫法

css 這樣寫是錯的

.wrapper .bg-green:nth-child(2) {
  background-color: green;
}

原因為:
.wrapper .bg-green:nth-child(2) 這個 selector 的意思是:選到 .wrapper 這一層裡面的第二個子元素,且要是 .bg-green

但是,.wrapper 裡面的第二個子元素是 <div>row2</div>,並不是 .bg-green,所以就選不到任何東西

css 正確寫法

要寫 .wrapper .bg-green:nth-child(3),才會選到「.wrapper 這一層裡面的第三個子元素,且要是 .bg-green

會先看 :nth-child(3) (是否為這一層裡面的第三個子元素),然後才看是否為 .bg-green

.wrapper .bg-green:nth-child(3) {
  background-color: green;
}

CSS Selector:before 與 after

參考資料:偽元素一覽表

Pseudo Element (偽元素),可以選到「元素裡面的某個部份」

html:

    <div class="price">
      999
    </div>

css:

  • 偽元素,一定要有的屬性是 content,代表「偽元素裡面要裝的內容」
    • 沒有 content 的話,偽元素就不會出現
    • 也可以調整 content 的文字顏色,例如:
      .price::before {
      content: '$';
      color: orange;
      }
      

attr() 抓出屬性的值

範例一

html:

    <div class="price">
      999
    </div>

css:
attr() 小括號裡面放入這個 html 標籤的屬性
可以用 attr(class) 把 class 這個屬性的值給抓出來
因此,attr(class) 就會是 price

.price::before {
  content: attr(class);
  color: orange;
}

範例二

html:
我自定一個屬性叫做 data-symbol="NTD"

    <div class="price" data-symbol="NTD">
      999
    </div>
    <div class="price" data-symbol="USD"">
      30
    </div>

css:

.price::after {
  content: attr(data-symbol);
  color: orange;
}

CSS Selector 的權重

補充:

為什麼數字之間要有逗號而不是直接變成數字呢?那是因為如果你沒有逗號的話很容易誤解,像是用了 12 個 class 會變 120,用了一個 id 會變 100,你會以為 class 會蓋掉 id,但其實不是的,因為權重是:

12 個 class:0, 12, 0

1 個 id:1, 0, 0

意思是說無論你有幾個 class,你都不可能蓋掉 id,因為 id 權重永遠都比 class 高,不是逢十就能進位。

延伸閱讀:強烈推薦收藏好物 – CSS Specificity (CSS 權重一覽)
延伸閱讀:你對 CSS 權重真的足夠了解嗎?

權重計算的原則:

原則一:越詳細的贏

!important > inline style > id > class > 標籤

  • inline style 是 1, 0, 0, 0
  • !important 是 1, 0, 0, 0, 0

舉例:
樣式 A 用了「一個 id、三個 class」就是 1, 3, 0
樣式 B 用了「15 個 class」就是 0, 15, 0

樣式 A 永遠都會蓋過樣式 B (不會逢十就進位)

原則二:當「權重完全一樣」時,「後面的樣式」就會蓋掉「前面的樣式」


#css







Related Posts

筆記:深入探討 JavaScript 中的參數傳遞:call by value 還是 reference?

筆記:深入探討 JavaScript 中的參數傳遞:call by value 還是 reference?

[ 筆記 ] 交換資料 - XMLHttpRequest、CORS、JSONP

[ 筆記 ] 交換資料 - XMLHttpRequest、CORS、JSONP

[C#] Asp.net Mvc 使用 AntiForgery

[C#] Asp.net Mvc 使用 AntiForgery


Comments