Elaine's Blog 朝著 senior 前進的工程師

CSS 學習筆記

2019-09-19
CSS

CSS 的魔法

csszengarden 這網頁裡面的 HTML 是一模一樣的,只是載入不同的 CSS 樣式 而已

引入樣式的方法

  • 內聯

    <div style="color: red;">
      這是哪裡啊
    </div>
    
  • 內部引入

    <head>
      <style>
        div {
          color: red;
        }
      </style>
    </head>
    
  • 外部引入

    <!-- 這裡是 index.html -->
    <head>
      <link rel="stylesheet" type="text/css" href="./index.css" />
    </head>
    
    /* 這裡是 index.css */
    div {
      color: red;
    }
    
越靠近的,權重越高 => 內聯

CSS 語法

先選到你要改變的元素,再來套用規則

div {
  color: red;
  text-align: center;
}

選擇器

  • id 選擇器
    • #myid { color: red; }
  • class 選擇器
    • .myclass { color: red; }
  • tag 選擇器
    • div { color: red; }
  • 組合選擇器
    • 後代選擇器
      • div p { color: red; }
      • 兒子和孫子都會被選到
    • 子代選擇器
      • div > p { color: red; }
      • 只有兒子會被選到
    • 相鄰選擇器
      • div + p { color: red; }
      • 只有第一個弟弟才被選到
    • 兄弟選擇器
      • div ~ p { color: red; }
      • 後面的弟弟才被選到
  • 偽類選擇器

    • :hover
      • 滑鼠在元素上的時候
    • :active
      • 點擊元素的時候
    • :disabled
      • 元素禁用的時候
    • :first-child
      • 匹配到的第一個元素
    • :last-child
      • 匹配到的最後一個元素
    • :nth-child(n)
      • 匹配到的第 n 個元素
      • 注意:n 從 1 開始算
      • n 為 odd 代表 匹配到的第「奇數」個
      • n 為 even 代表 匹配到的第「偶數」個
  • 偽元素

    • 「偽元素」之所以稱作「偽」,除了英文從「Pseudo」翻譯過來之外,就是因為它並不是真正網頁裡的元素,但行為與表現又和真正網頁元素一樣,也可以對其使用 CSS 操控
      • 優點:
        • 不佔用 DOM 節點,減少 DOM 節點數量
        • 避免增加毫無意義的頁面元素
      • 缺點: - 偽元素不真正在 HTML 內容中體現,只在視覺效果上體現,所以不能給偽元素添加具有實際意義的內容,這部分內容不會搜索引擎抓取
    • ::before 預設在 原本內容
    • ::after 預設在 原本內容
    • 一定要具備 content 的屬性,不然顯示不了
    • 為了和「偽類選擇器」做區隔
      • W3C 定義「偽元素」使用 ::
      • 而「偽類選擇器」則使用 :
      • 但現在瀏覽器就算寫一個冒號 : 也可以
  • 選擇器權重
    • !important > id > class > tag
    • 自己 > 爸爸 > 阿公
    • 自己 id > 自己 class > 自己 tag > 爸爸 id > 爸爸 class > 爸爸 tag > 阿公 id > 阿公 class > 阿公 tag

字型

  • font
    • font-size 改變字體大小
      • 大部分瀏覽器預設是 16px
    • font-family 改變字型
      • 用逗號 , 隔開每個你想設定的字型,接著的工作就讓瀏覽器自己去判斷
      • 字型設定並不會自動下載字型檔案,如果用戶端沒有你設定的字型,有可能無法正確顯示你要的效果,所以建議除了明確字型之外,最好要加上通用字型,以確保網頁呈現
    • font-weight 改變粗體細體
      • bold
      • 100、200、300…900
div {
  font-size: 20px;
  font-family: serif, sans-serif, cursive, fantasy, monospace;
  font-weight: bold;
}

顏色

  • color 改變文字顏色
  • background-color 改變背景顏色
  • 設定顏色
    • 十六進制 Hex
      • 例如 #FF0000
    • RGB
      • 例如 RGB(255, 0, 0)
    • 常用的顏色
      • 例如 redbluegreenyellowwhiteblack 等等
button {
  color: #ffffff;
  background-color: #4a86e9;
}

邊框

  • border
    • border-width 邊框粗細
    • border-style 邊框類型
      • solid 實線
      • dashed 虛線
    • border-color 邊框顏色
    • border-radius 邊框圓角
button {
  border: 1px solid red;
  border-radius: 16px;
}

/* 等價於這樣寫 */
button {
  border-width: 1px;
  border-style: solid;
  border-color: red;
  border-radius: 16px;
}

文字對齊

  • text-align
    • left
    • center
    • right

透明度

  • opacity
    • 設定範圍 0 ~ 1
    • 1 代表完全不透明
    • 0 代表完全透明

游標

  • cursor
    • pointer 讓人看起來可以點

box-model 盒模型

每一個東西都是一個盒子(Box)

  • margin 外面距離
  • border 邊框
  • padding 裡面距離
  • width 寬度
  • height 高度

margin 與 padding

  • marginpadding 最大的差別?
    • 點擊範圍含 borderpaddingwidthheight,不包含 margin
  • margin 語法 (padding 一樣)
    • 1 個數值,上下左右
    • 2 個數值,上下 左右
    • 3 個數值, 左右
    • 4 個數值, ,順時針
    • auto,讓瀏覽器自己去設定
button {
  padding: 8px;
  padding: 8px 16px;
  padding: 8px 16px 10px;
  padding: 8px 16px 10px 16px;
}

display

  • block
    • 總是獨佔一行 (width 100%)
    • div、form、h1、h2、h3、h4、h5、h6、hr、ol、p、table、ul、li
  • inline
    • 看內容多大就多大,和別人併排
    • 無法設定 width、height、padding-top、padding-bottom、margin-top、margin-bottom
    • a、img、input、label、select、span、textarea
  • inline-block
    • 看內容多大就多大,和別人併排
    • 可以設定 width、height、padding-top、padding-bottom、margin-top、margin-bottom

隱藏元素

display: nonevisibility: hidden 都可以隱藏元素

  • display:none 不會佔空間
  • visibility:hidden 會保留原本的空間

寬度與高度

  • height 高度
  • min-height 最小高度
  • max-height 最大高度
  • width 寬度
  • min-width 最小寬度
  • max-width 最大寬度

  • 規則

    • height > max-height 時,會吃 max-height
    • height < max-height 時,會吃 height
    • min-height > max-height > height 時,會吃 min-height
  • 例如:試試看縮放視窗

    div {
      width: 50%;
      min-width: 100px;
      max-width: 300px;
    }
    
  • 設置 height: 100% 無效?

    • 原因
      • 可能是因為父元素沒有設定 heightpx%,此時父元素會根據子元素的高度而撐開,導致子元素的 height: 100% 失去基準值而無效
    • 解決
      • 方法 1
        • 幫父元素設置 height 且單位為 px%emrem
      • 方法 2
        • 一路從 <html><body>、…、父元素(全部祖先)都設置 height: 100%
    • 參考資料
  • 如何讓 height 與 width 變成實際的長寬?

    • box-sizing: border-boxheight (width) = border + padding + height (width)

長度單位

  • px
    • pixels 像素
    • 相對於顯示設備,相對於「顯示設備 pixel 的高度/寬度」
  • %

    • 以父容器高 / 寬度作為基準

      屬性 100% 的基準
      padding 父容器寬度
      margin 父容器寬度
      width 父容器寬度
      height 父容器高度
  • vw
    • 以瀏覽器可視寬度作為基準
    • 1vw = 瀏覽器可視寬度的 px / 100
  • vh
    • 以瀏覽器可視高度作為基準
    • 1vh = 瀏覽器可視高度的 px / 100
  • em

    • 當下 font-size 的字母(大寫) M

      <head>
        <style>
          body {
            font-size: 14px;
          }
      
          .parent {
            font-size: 1.5em; /* 14px * 1.5 = 21px */
          }
      
          .child {
            font-size: 1.3em; /* 21px * 1.3 = 27.3px */
          }
        </style>
      </head>
      <body>
        <div class="parent">
          parent
          <div class="child">
            child
          </div>
        </div>
      </body>
      
  • rem

    • 相對於「根元素字型的大小」,等同於相對 <body>em

      <head>
        <style>
          body {
            font-size: 14px;
          }
      
          .parent {
            font-size: 1.5rem; /* 14px * 1.5 = 21px */
          }
      
          .child {
            font-size: 1.1rem; /* 14px * 1.1 = 15.4px */
          }
        </style>
      </head>
      <body>
        <div class="parent">
          parent
          <div class="child">
            child
          </div>
        </div>
      </body>
      

定位元素

  • position

    • static
      • 原本的位置 (預設)
    • relative
      • 相對原本的位置
    • absolute
      • 絕對定位
      • 對齊點最近「非 static 」特性的祖先 (就是 relative、absolute)
      • 沒找到的話,就去對 <body>
    • fixed
      • 相對瀏覽器的位置
      • 無視捲軸的滾動,就是固定在那裡
    • sticky
      • relativefixed 合體
      • 一開始為 relative,滾輪滾到某個程度,會轉為 fixed
      • 需指定 toprightbottomleft,才會生效
      • 瀏覽器支援度較低
  • position: static

    <div class="box box1">box1</div>
    <div class="box box2">box2</div>
    <div class="box box3">box3</div>
    
    .box {
      height: 100px;
      width: 200px;
    }
    
    .box1 {
      background: red;
    }
    
    .box2 {
      background: blue;
    }
    
    .box3 {
      background: green;
    }
    
  • position: relative

    .box {
      height: 100px;
      width: 200px;
    }
    
    .box1 {
      background: red;
    }
    
    .box2 {
      background: blue;
      position: relative;
      top: 10px;
      left: 30px;
    }
    
    .box3 {
      background: green;
    }
    
  • position: fixed

    .box {
      height: 100px;
      width: 200px;
    }
    
    .box1 {
      background: red;
    }
    
    .box2 {
      background: blue;
      position: fixed;
      top: 10px;
      left: 30px;
    }
    
    .box3 {
      background: green;
    }
    
  • position: absolute

    <div class="wrapper">
      <div class="box box1">box1</div>
      <div class="box box2">box2</div>
      <div class="box box3">box3</div>
    </div>
    
    .wrapper {
      margin: 50px;
      border: 5px solid yellow;
      width: 400px;
    }
    
    .box {
      height: 100px;
      width: 200px;
    }
    
    .box1 {
      background: red;
    }
    
    .box2 {
      background: blue;
      position: abosulte;
      top: 10px;
      left: 30px;
    }
    
    .box3 {
      background: green;
    }
    

浮動式排版 - float

float: leftfloat: right 兩種可供選擇 它會將該元素整個往左、往右移並脫離網頁原先流向

更強大的排版工具 - Flexbox

  • 分為兩種
    • Flex Container 父容器
    • Flex Item 子項目
  • 方向
    • main axis 主軸
    • cross axis 交叉軸(垂直主軸)
  • 父容器
    • display: flex
    • flex-direction 設定主軸的方向
      • row 左->右
      • row-reverse 右 -> 左
      • column 上 -> 下
      • column-reverse 下 -> 上
    • justify-content 主軸的對齊方式
      • flex-start 主軸的起點 (預設)
      • flex-end 主軸的終點
      • center 主軸中間
      • space-between 剩餘的空間平均分配,起點和終點沒有
      • space-around 剩餘的空間平均分配
    • align-items 交叉軸的對齊方式
      • flex-start 交叉軸的起點
      • flex-end 交叉軸的終點
      • center 交叉軸中間
      • stretch 延伸
      • baseline 與文字基線對齊
    • flex-wrap 當子層的數量太多,可以決定要不要換行
      • nowrap 不換行(預設)
      • wrap 換行
      • wrap-reverse 換行時反轉
  • 子項目

    • flexflex-growflex-shrinkflex-basis 的縮寫
    • flex-grow 伸展的比例 (空間還有多的時候,我分到剩下空間的比例)
      • 值是數字且無單位,不可以為負值
      • 預設是 0,代表不會放大
    • flex-shrink 壓縮的比例 (空間不夠時,我可以壓縮我自己的比例)
      • 值是數字且無單位,不可以為負值
      • 預設是 1,代表要壓縮的話,我可以算 1 等分
    • flex-basis 項目的基準值
      • 值可以是 %pxemrem
      • 如果主軸是 rowrow-reverseflex-basis 等同於設置 width
      • 如果主軸是 columncolumn-reverseflex-basis 等同於設置 height
    • order 重新定義排列順序
      • 從小排到大
  • 詳細 flex-growflex-shrink 的計算公式

    • 參考 详解 flex-grow 与 flex-shrink
    • flex-grow

        子 1 子 2 子 3
      寬度 500px 100px 150px 100px
      flex-grow   1 2 3
      • 所以剩餘空間為 500px - 100px - 150px - 100px = 150px
      • 權重總和是 1 + 2 + 3 = 6
      • 子 1 還可以多分 = 150px * 1/6 = 25px
      • 子 2 還可以多分 = 150px * 2/6 = 50px
      • 子 3 還可以多分 = 150px * 3/6 = 75px
        子 1 子 2 子 3
      寬度 500px 100px 150px 100px
      flex-grow   1 2 3
      還可以多拿   25px 50px 75px
      最後顯示的寬度   125px 200px 175px
    • flex-shrink

        子 1 子 2 子 3
      寬度 500px 150px 200px 300px
      flex-shrink   1 2 3
      • 所以不夠空間 = 500px - 150px - 200px - 300px = -150px
      • 權重總和 1 * 150px + 2 * 200px + 3 * 300px = 1450px
      • 子 1 可以壓縮 = 150px * ((1 * 150px) / 1450px) = 15.5px
      • 子 2 可以壓縮 = 150px * ((2 * 200px) / 1450px) = 41.4px
      • 子 3 可以壓縮 = 150px * ((3 * 300px) / 1450px) = 93.1px
        子 1 子 2 子 3
      寬度 500px 150px 200px 300px
      flex-shrink   1 2 3
      可以壓縮   15.5px 41.4px 93.1px
      最後顯示的寬度   134.5px 158.6px 206.9px

overflow 溢位

當內容超過元素的大小時,會產生 overflow

  • overflow
    • overflow: visible
      • 會呈現在元素框外
      • 預設值
    • oveflow: hidden
      • 內容會被修剪,超出的地方就看不到了
    • overflow: scroll
      • 內容會被修剪,但是瀏覽器會顯示滾動條,以便查看其餘內容
    • overflow: auto
      • 如果內容被修剪,則會出現滾動條

圖層關係

  • z-index 圖層順序
    • 數字越大越上面

讓網頁排版在各瀏覽器快速一致化的重置歸零

W3C 制訂 HTMLCSS 規格時,並沒有強制規定各家瀏覽器應該怎樣實作每一個 HTML tag 的 CSS 預設樣式,導致各家瀏覽器顯示差異

  • 重置 CSS
    • CSS Reset
      • 做法是把所有瀏覽器最不一致的地方強制歸 0
      • 優點是統整、重置了各個瀏覽器的樣式設定
      • 缺點是必須全部重新做設定,比較沒有彈性,而且在使用開發者工具時會看到一大坨的繼承鏈
    • Normalize CSS
      • 保留有用的瀏覽器默認設置,而不是將其刪除
      • 為廣泛的 HTML 元素提供一般化的樣式
      • 修正瀏覽器的 Bug 與不一致
      • 透過微妙的改善提高可用性
      • 有詳細的文檔來解釋代碼
/* reset.css */
html,
body,
div,
span,
applet,
object,
iframe,
h1,
h2,
h3,
h4,
h5,
h6,
p,
blockquote,
pre,
a,
abbr,
acronym,
address,
big,
cite,
code,
del,
dfn,
em,
font,
img,
ins,
kbd,
q,
s,
samp,
small,
strike,
strong,
sub,
sup,
tt,
var,
dl,
dt,
dd,
ol,
ul,
li,
fieldset,
form,
label,
legend,
table,
caption,
tbody,
tfoot,
thead,
tr,
th,
td {
  margin: 0;
  padding: 0;
  border: 0;
  outline: 0;
  font-weight: inherit;
  font-style: inherit;
  font-size: 100%;
  font-family: inherit;
  vertical-align: baseline;
}
/* remember to define focus styles! */
:focus {
  outline: 0;
}
body {
  line-height: 1;
  color: black;
  background: white;
}
ol,
ul {
  list-style: none;
}
/* tables still need 'cellspacing="0"' in the markup */
table {
  border-collapse: separate;
  border-spacing: 0;
}
caption,
th,
td {
  text-align: left;
  font-weight: normal;
}
blockquote:before,
blockquote:after,
q:before,
q:after {
  content: "";
}
blockquote,
q {
  quotes: "" "";
}

變形

  • transform 變形
    • translate 平移
    • rotate 旋轉角度
    • scale 放大縮小
對 transform 有興趣的也可以參考我之前在公司前端分享會的主題 - Transform 變形
div:hover {
  transform: translate(30px, 40px) rotate(90deg) scale(1.2);
}

動畫效果

CSS3 中有兩個用來做動畫的屬性,一個是 Transition,另一個是 Animation

  • transition 過渡動畫
    • 在給定的持續時間內平滑地更改屬性值(從一個值到另一個值)
    • transition: [property 名稱] [duration 時間] [timing-function 特效] [delay 延遲]
      • 屬性名稱為 all,代表所有屬性都套用
<div class="box"></div>
.box {
  width: 100px;
  height: 100px;
  background: blue;
  transition: width 0.3s ease-in;
}

.box:hover {
  width: 200px;
  height: 200px;
  background: red;
}

陰影效果

vertical-align

  • 用來指定行內元素(inline)或表格單元格(table-cell)元素的垂直對齊方式
  • MDN - vertical-align

置中對齊的方法

其他可以參考 CSS 垂直置中技巧,我只會 23 個,你會幾個

  1. 文字水平置中 - text-align

    <div class="content">Lorem ipsam.</div>
    
    .content {
      text-align: center;
      width: 400px;
      background: #ccc;
    }
    
  2. 單行文字垂直置中 - line-height

    <div class="parent">
      <div class="child">
        Lorem ipsam.
      </div>
    </div>
    
    .parent {
      border: 1px solid black;
      width: 400px;
      height: 100px;
    }
    
    .child {
      line-height: 100px;
      background: #ccc;
    }
    
  3. block 塊級水平置中 - margin auto

    <div class="parent">
      <div class="child"></div>
    </div>
    
    .parent {
      width: 400px;
      border: 1px solid black;
    }
    
    .child {
      width: 100px;
      height: 100px;
      background-color: blue;
      margin: 0 auto;
    }
    
  4. 絕對定位水平垂直置中 - position + translate

    <div class="parent">
      <div class="child"></div>
    </div>
    
    .parent {
      width: 400px;
      height: 300px;
      border: 1px solid black;
      position: relative;
    }
    
    .child {
      width: 100px;
      height: 100px;
      background-color: blue;
      position: absolute;
      top: 50%;
      left: 50%;
      transform: translate(-50%, -50%);
    }
    
  5. flexbox

    <div class="parent">
      <div class="child"></div>
    </div>
    
    .parent {
      width: 400px;
      height: 300px;
      border: 1px solid black;
      display: flex;
      justify-content: center;
      align-items: center;
    }
    
    .child {
      width: 100px;
      height: 100px;
      background-color: blue;
    }
    

Content