CSS - 裝潢你的網站


Posted by ai86109 on 2020-08-02

如果說網頁是一棟大樓,HTML 是他的骨幹(鋼筋水泥),那 CSS 就是裝潢了。

CSS 是 Cascading Style Sheets(階層式樣式表)的縮寫,顧名思義它就是用來更改樣式的。

改變樣式的三種方式

有三種方式可以改變樣式:

(1)加在 tag 裡面

<div style="background: red;">
        hello
</div>

(2)加在 head 中

格式為:

<head>
    <style>
        selector {
            attribute: value;
        }
    </style>
</head>

所以可以寫成

<head>
    <style>
        div {
            background: red;
        }
    </style>
</head>
<body>
    <div>
        hello
    </div>
</body>

(3)開一個css檔案再引入

@index.html

<head>
    <link rel="stylesheet" href="./index.css">
</head>
<body>
    <div>
        hello
    </div>
</body>

@index.css

div {
    background: yellow;
}

第三種方式在維護上會比前兩種容易。


CSS selector

要先選到你想改變的東西才能改變,這很好懂,所以這部分就是要講怎麼選到你要的元素。

第一個要說 universal selectors

* {
    color: white;
}

使用*就可以選到所有 HTML 的元素

或是可以使用標籤名稱

div {
    background: yellow;
}

這樣可以選到所有 div 標籤。

但通常我們不會選所有標籤,常用的方法是使用 id or class。
id 只會有一個,不會重複;而 class 可以有很多個,同一個 tag 裡面可以有不只一個 class。

@index.html

<div id="hello1">
    hello1
</div>
<div class="bg-yellow">
   hello2
</div>
<div class="bg-yellow text-green">
    hello3
</div>

@index.css

#hello1 {
    background: green;
}

.bg-yellow {
    background: yellow;
}

.text-green {
    color: green;
}

那能不能同時符合多個條件才執行?

條件要連著寫,不能有空格,像是以下:

@index.html

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

@index.css

span.bg-yellow {
    background: yellow;
    color: red;
}

.bg-yellow {
    background: yellow;
}

.bg-yellow.text-green {
    background: yellow;
    color: green;
}

剛剛講的都是同一階層,那如何去調整下面的階層?

a > b 表示這個效果是對 a 下面那一層的 b
a b 表示這個效果是對 a 下面所有的 b

@index.html

<div class="lv1">
    lv1
    <div class="lv2">
        lv2-1
        <div class="bg-yellow">
           lv3
        </div>
    </div>
    <div class="bg-yellow">
        lv2-2
    </div>
</div>

@index.css

.lv1 > .bg-yellow {
    background: yellow;
}

這邊只有 lv2-2 會變黃色

.lv1 .bg-yellow {
    background: yellow;
}

這邊 lv3 和 lv2-2 都會變黃色

接下來要介紹 ~+
a ~ b 表示這個效果是對 a 同一層下面所有同一層的 b
a + b 表示這個效果是對 a 同一層所有符合 a 下面緊鄰的 b

@index.html

<div class=“b”>1</div>
<div>2</div>
<div class="a">3</div>
<div class="b">4</div>
<div class="b">5</div>

@index.css

.a ~ .b {
    background: red;
}

4 & 5 會是紅色

.a + .b {
    background: red;
}

4 會是紅色

pseudo-classes

另外還有 pseudo-classes,例如::hover,當做到指定動作時才會觸發。

但因為必須要觸發才會有效果,所以如果需要 debug 會很麻煩。

此時可以使用 檢查 > element > 先按到想要 debug 的那個 HTML 程式碼 > 下面的style > toggle element state > 可以讓他維持在那個狀態下。

nth-child

接下來要講一個很有趣的 selector 叫 nth-child

@index.html

<div class="wrap">
    <div>1</div>
    <div>2</div>
    <div>3</div>
    <div>4</div>
    <div>5</div>
</div>

@index.css

.wrap div:first-child {
    background: red;
}

第一行就會變成紅色,如果用 last-child,最後一行就會變紅色。

如果改成以下:

.wrap div:nth-child(3) {
    background: red;
}

就能指定第三行,如果(odd)就是奇數,(even)就是偶數,也可以用數字帶(3n)就是 3 的倍數,(2n+1)就是奇數。

那如果我們稍微改一下

@index.html

<div class="wrap">
    <div>1</div>
    <div class="bg">2</div>
    <div>3</div>
    <div class="bg">4</div>
    <div>5</div>
</div>

@index.css

.wrap .bg:nth-child(1) {
    background: red;
}

照理說應該是第二行會變色吧!但實際上是不會有顏色出現,原因是這邊會先去找第一行,再看他有沒有 bg 這個 class,條件符合才會顯現。

所以如果要讓第二行出現顏色要改成:

.wrap .bg:nth-child(2) {
    background: red;
}

pseudo-element

前面有講到 pseudo-classes,這邊要講的是
pseudo-element(偽元素)

直接示範比較好懂

@index.html

<div class="wrap">
    1000
</div>

@index.css

.wrap::before {
    content: '$';
    color: red;
}

就會得到 $ 1000,$ 會是紅色的
可以直接創造內容,這就是為什麼叫做偽元素的原因
同理,::after 就是會出現在後面

.wrap::after {
    content: ‘NTD’;
    color: red;
}

其實 content 除了自己輸入外,還有其他方法

@index.html

<div class="wrap">
    1000
</div>

@index.css

.wrap::before {
    content: attr(class);
    color: red;
}

就會印出 wrap 1000
我們也可以自訂元素,而通常都是以 data 開頭
但要 content 要記得寫,不然都不會生效

@index.html

<div class="wrap" data-symbol="$">
    1000
</div>

@index.css

.wrap::before {
    content: attr(data-symbol);
    color: red;
}

權重

最後要講到 CSS selector 的權重。

基本規則就是 id > class(class, pseudo-class, attribute) > tag
可以把他看做三組數字比較,由左至右比較,第一個贏就贏了,平手才往下繼續比。

0, 1, 0

.wrap {
    color: red;
}

0, 3, 2

div.wrap > div.list > .item {
    color: blue;
}

1, 0, 0

#price {
    color: pink;
}

所以就是 pink,如果數字都一樣,後者勝。

但除了這三個之外還有兩個權重更高的。

第一個是 inline style,就是直接寫在 tag 裡面

<div class="wrap">
   <div class="list">
        <div class="item" id="price" style="color: aqua;">
            1000
        </div>
    </div>
</div>

權重為 1, 0, 0, 0

第二個是 !important,可以覆蓋掉所有

1, 0, 0, 1, 0

.wrap {
    color: red !important;
}

0, 3, 2

div.wrap > div.list > .item {
    color: blue;
}

1, 0, 0

#price {
    color: pink;
}

但這兩種很少使用,因為會使專案維護變得困難

另外要注意,為什麼數字之間要有逗號而不是直接變成數字呢?那是因為如果你沒有逗號的話會很容易誤解,像是用了 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权重真的足够了解吗?


各種裝飾

你已經可以靠著前面說的一大堆方法選到你要的元素了,選到之後就要來改變他的各種狀態啦。

背景

第一個要說 background,有幾種方法

(1)直接填顏色

.box {
    background: red;
}

(2)填色碼

.box {
    background: #f0f0f0;
}

(3)rgb

.box {
    background: rgb(244, 0, 128);
}

(4)rgba (a 是透明度,數值是 0~1)

.box {
    background: rgb(244, 0, 128, 0.5);
}

(5)除了顏色之外也可以用圖片

.box {
    background: url(圖片位置);
}

如果這時候你看不見整張圖片,可以透過設定 width & height 的方式調整,但如果你的長寬設的比圖片還大,這時候可能你會發現圖片重複了。

如果不想要重複請加上 no-repeat

.box {
    background: url(圖片位置) no-repeat;
    width: 500px;
    height: 500px;
}

那如果你的長寬設不夠時,此時只會顯示圖片的一部份,但這時候我可能只想要圖片的正中央怎辦?

.box {
    background: url(圖片位置) no-repeat center center;
    width: 50px;
    height: 50px;
}

第一個是 y軸,第二個是 x軸,所以同理想要右下角就是 bottom right

到目前為止都是修改我們範圍的長寬,圖片都是原本 size

那可以直接修改圖片大小嗎?

background-size: 300px 200px;

這邊也可以設為 %
background-size: 100% 100%;
這時就會去符合我們設定的長寬了

還有兩個很常用的,一個是 contain
background-size: contain;
他會自動對齊可以對齊的長或寬,重點是可以看到整張圖片&比例和原圖一樣。

另一個是 cover
background-size: cover;
他會使圖片佔滿你目前的長寬(你拉動瀏覽器他會動態填滿),但圖片顯示的範圍也會動態調整。

還有很多其他屬性可以透過,檢查 > 找到你要的 background > 有個箭頭點下後可以看到。

border & padding & margin

接著要說 border,也就是邊框。

要注意 border 是會影響整體寬高的

.box {
    background: red;
    width: 30px;
    height: 30px;
    border: 10px solid green;
}

所以這裡的寬就是 30 + 10 + 10 = 50px
border-style 可以調邊框的樣式

覺得邊框不夠圓滑嗎?可以用 border-radius

.box {
    background: red;
    width: 30px;
    height: 30px;
    border: 10px solid green;
    border-radius: 50%;
}

設成 50% 就會剛好是圓形

既然可以畫出圓形,那三角形可以嗎?

將 border 的四個邊設成不同顏色,就可以發現其實形狀會是梯形,當 width & height 為 0 時,四個邊就會變成四個三角形了。

只要將其中三個邊顏色設為 transparent,三角形就出現了。

\

有一個跟 border 很像的是 outline,差別在於 outline 是往外擴張,並不會影響整體寬高。

outline: 5px solid green;

但其實實際開發上並不常用到。

再來是 padding & margin

其實跟剛剛的 border & outline 很像,這邊就是邊距的意思,padding 往內推,會影響整體寬高;margin 則是往外推。

我們這邊可以看到 Chrome 瀏覽器在我們還沒做任何事時,就會自動先幫我們加上邊距
若要去除,可以加上:

body {
    margin: 0px;
}

reset.css vs normalize.css
https://ithelp.ithome.com.tw/articles/10196528

文字相關

接下來要講和文字相關的 CSS

.box {
    color: grey;
    font-size: 30px;
    font-weight: bold;
    font-family: fantasy;
    letter-spacing: 2px;
    line-height: 1.5em;
    text-align: center;
}

font-size 在瀏覽器最小就是 12px
font-weight 也可以用數字 100~900
font-family 如果有支援就可以用,沒支援就會跳回預設的
letter-spacing 字距
line-height 可以用 px,也可以用 em,1.5em 就是 1.5 倍行高的意思
text-align 可以調置左置中置右

em 以母元素的基礎字體大小作為倍數的單位
ex: 母元素 12px, 1em = 12px, 2em = 24px
rem 以根元素的基礎字體大小作為倍數的單位
ex: 1rem = 12px

//那如果高度也要置中呢?這邊有個小技巧

如果只有一行字,line-height 調成跟 height 一樣即可
如果有多行字,可以先把 height 刪掉,再使用 padding 去推

除了上面這些外,當你有設定寬,而文字太長超過寬度時,他會換行
word-break 就是決定斷句的位置

word-break: break-all;
break-all 是到寬度就直接換
break-word 是到寬度而文字擺不下時,將該文字移到下一行

另一個是 white-space,預設的時候不管你空白或換行,都只算一個空白而已
white-space: nowrap;
//nowrap 就是不要將文字包起來,效果就是文字不換行

white-space: pre;
//會保留你在程式碼的空白&換行

white-space: pre-line;
//會保留換行

OK,那文字超出去,可以藏起來嗎?

這邊就要使用 overflow

overflow: hidden;
//hidden 可以將超出的東西隱藏(不只有針對文字),scroll 會有拉軸滑動

另一個很像的是 text-overflow,是針對文字使用的

text-overflow: ellipsis;
//ellipsis 可以將超出的字變成...

但如果要造成這個效果必須滿足幾個條件:
要先用 white-space: nowrap 讓字不換行,這不換行的字還要超出 width,超出的字要 overflow: hidden;,才會出現 text-overflow: ellipsis; 這個效果。

transition

當你做了會改變狀態的事,如 :hover 等等

滑鼠移過去時,會瞬間變化,那要如何做出『漸變』呢?用 transition

#price {
    width: 150px;
    height: 150px;
    border: 10px solid green;
    border-radius: 50%;
    font-size: 30px;
    font-family: fantasy;
    line-height: 150px;
    text-align: center;
    transition: all 0.6s ease-in-out;
}

#price:hover {
    color: white;
    background: grey;
    border: 10px solid grey;
}

transition 有三個參數(對哪個屬性作用, 幾秒, 預設的漸變動畫)

這邊要注意如果把 transition 放在 :hover 那邊,放開時會失去 transition 的效果。

transform

最後要講到 transform,這是一個有很多功能的裝飾。

例如 transform: scale(2);
以中心放大兩倍

transform: rotate(180deg);
就會轉180度

所以搭配 transition 可以製造出很多效果。

還有 transform: translate(50px, -20px);
就會往右移 50px,往下移 20px

那你會想這有什麼用,不是可以用 position 就可以更動了嗎?

其實不然,translate 他不會影響其他元素,所以在動畫裡要移位子都是用這個比較多。

但這個 translate 還有另一個妙用,假設我今天想讓 box1 在畫面的正中央

.box1 {
    position: absolute;
    width: 150px;
    height: 150px;
    background: red;
    top: 50%;
    left: 50%;
}

此時這個 box1 的左上角會在畫面的正中央,那要怎麼讓他的中心的對到畫面正中央呢
利用 transform。

.box1 {
    position: absolute;
    width: 150px;
    height: 150px;
    background: red;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
}

這裡的 50% 是指 box1 寬&高的 50%,所以 box1 就會被移到想要的位置上了

盒模型 box model

盒模型 box model 是 CSS 中很重要的東西。

必須了解 width, height, padding, border, margin 對於 box 大小的關係
預設情況下是 box-sizing: content-box;
也就是固定 content 的寬高,再加上 padding & border
那有沒有辦法 border 固定寬高呢?
box-sizing: border-box;

Display

除此之外也要知道 display 的三種形式 block, inline, inline-block

block

第一個是 block,block 你要調什麼都可以(border, padding 等等)

代表元素有 div, h1, p

inline

再來是 inline,調 width, height 都沒用,是根據內容去顯示。
調 margin 只有左右會動,上下不會
調 padding 左右會動,調上下只有背景會動,但不影響元素位置

代表元素是 span, a

inline-block

最後是 inline-block
對外像 inline 一樣可以併排,對內像 block 可調各屬性,與 block 的差別就在能否並排而已。

代表元素是 button, input, select

inline-block 之間可能會有間隙的原因是因為你程式碼有空格(換行),可以用註解填補:
Inline-Block元素多出來的間隙

其實除了上面這些之外,還有像是 float, flex box, grid 等排版。

在使用時機上各有其強項,例如:
若要做出文繞圖,或是要支援 IE11以下的,會使用 float
flex 較適合單一元件下單一排版時
grid 較適合在 HTML 結構有巨大變化,還有二維排版

以下用來熟悉這些 display 的小遊戲:

flex
flexbox froggy
flexbox pirate
flexbox 介紹

grid
grid garden
grid 介紹

position

最後要說到定位 position

預設是 static ,會照順序排列下去
如果更動它的位置,會牽一髮動全身。

那如果 position: relative;
調整他的位置時,並不會影響到其他元素的位置。

position: fixed;
則是針對 viewport(瀏覽器你看得到地方)去做定位。

position: absolute;
針對某個參考點進行定位

那什麼可以當作參考點?就是往上找,第一個不是 static 的點
所以通常我們會想將要移動的元素 position 設為 absolute
基準點的 position 設為 relative
*這邊要注意的是,設為 absolute 的東西,會脫離原本的坐標系,由下一個元素遞補上來

其實 position 還有一個很新的,叫做 position: sticky;

.box {
    background: red;
    top: 10px;
    position: sticky;
    z-index: 2;
}

這個意思就是當你網頁往下滑,這個 box 此時處於 static,但當我們把網頁往下滑,他被移動到 viewport 距離 top 10px 時,你就可以把它想成 fixed,他會被定在那個位置。

z-index

再來說 z-index,其實就是階層,z-index 越大越前面,如 z-index: 1;,規則是先比 z-index,相同時再比先後順序。

在排版之前問自己幾個問題

  1. 元素是絕對定位還是相對定位?
  2. 元素相對於哪裡排版?
  3. 元素與相鄰元素相對關係?
  4. 元素內部怎麼排?

學習 CSS 版面配置


RWD, Response Web Design

RWD 的全名是 Response web design

使用時要在 head 加上這行

<meta name="viewport" content="width=device-width, initial-scale=1.0">

content="width=device-width
就是將顯示的寬度變成裝置寬度

initial-scale=1.0
則是縮放比例為一倍,將內容都等比例縮放

除了這兩個之外,其實還有其他屬性可用

例如像是 maximum-scale, user-scalable 等等
maximum-scale = 2
表示使用者最多可以放大兩倍去觀看

media query

接著要講 CSS media query
先看一段 code

.title{
    color: red;
}

@media(max-width:768px){
    .title{
        color: green;
    }
    .content{
        font-size: 30px;
    }
}

@media(max-width:375px){
    .title{
        color: blue;
    }
}

一般來說我們寫 CSS 都是最上面的那種寫法,但設計 RWD 時,我們會使用 @media,他可以在你達成指定的條件時,觸發此 CSS 語法。

所以當我們縮小寬度至 768px 時,顏色會變成綠色,字大小也會變成 30px;寬度持續縮到 375px 時,顏色會再變成藍色。

看起來好像滿容易的,但要注意一點,如果手機轉成橫向呢?
寬是會變的喔,所以就會 >375px,而變成綠色的了,這個部分在設計時也要特別注意!

另外,在寫程式碼時我們總不可能手動將瀏覽器縮成各種 size 吧。

在 devtool 裡就有內建可以模擬各種 size 的工具

左上角 toggle device toolbar > 可以選擇 device 或是自訂長寬

滑鼠移到螢幕上也會出現手指大小的圓圈,可以模擬使用者的手指,這樣在開發上會更加方便。

\

以往我們在寫寬度時會用 width,這樣寫用電腦看沒事,但在寬度比較小的載具上時,就會出現會需要左右滑動的狀態了。

其實這樣是一個十分不好的使用者體驗

這時可以用 max-width

在高解析度的畫面他跟 width 的功能一樣,但縮小 width 時,他就會自適應變窄,也就可以避免 x軸的 bar 出現了。

.wrap{
    max-width: 600px;
    margin: 0 auto;
    display: flex;
}

.menu{
    width: 30%;
}

.content{
    width: 70%;
}

所以我們可以在最外層使用 max-width,內層使用 percent 讓版面自適應。

補充:How To Write Mobile-first CSS


#css #RWD #css selector #display #position







Related Posts

[ 狀況題 ] 如何徹底將檔案從 Git 中移除?

[ 狀況題 ] 如何徹底將檔案從 Git 中移除?

{ 鼠年全馬鐵人挑戰 ;} Week 02 - 做一個影片背景的網頁吧

{ 鼠年全馬鐵人挑戰 ;} Week 02 - 做一個影片背景的網頁吧

[ 紀錄 ] 實戰練習 - 部落格 (以 Express 實作前端 + 後端)

[ 紀錄 ] 實戰練習 - 部落格 (以 Express 實作前端 + 後端)


Comments