# [CSS] 圖片要注意的細節 ###### tags: `前端筆記` `style` ## 為什麼想要理解? 因為我其實就算是用「背」的在處理圖片(比方來說一定要把 `img` 寫成 `display: block`)剛好這陣子看到 [網站開發「總是被忽視的圖片運用細節」 - #thef2e2021系列活動](https://www.youtube.com/watch?v=smzHWBRpfvk) 就決定要好好的理解原因,以及哪裡可以做的更好。 ## 要注意哪些細節呢? ### 首先來談談為什麼要把 `img` 設定成 `display: block` 呢? 因為 `img` 預設是 `display: inline-block`(`display: inline` 及 `display: inline-block` 的差別就是 inline 不會理我們寫的 `width` 及 `height`,但是 inline-block 會理)。雖然 `img` 預設是會理我們寫的 `width` 及 `height` 的 `display: inline-block`,不過在 `display: inline-block` 中卻有一個沒辦法解決的問題,不管怎樣下方都「會留空白」。 [範例一](https://codepen.io/lun0223/pen/vYJapOO) ![](https://i.imgur.com/WvG9NWB.png) **這個就是 `display: inline-block` 的缺點,即使可以設定排版,但是會有無法消除的空白。這也是為什麼使用 `display: block` 的原因,這樣子就可以直接填滿空白的部分。** ### 如果是內文的一部分就用 `<img>` 可以插入圖片的標籤是 `<img>`,但其實透過 CSS 的另一個屬性 `background-image` 也可以插入圖片,這邊先來探討 `<img>` 標籤除 `display: block` 之外的使用細節。 1. 外層容器的大小要確定 2. 多張圖片的話也要設定每個圖片容器要佔外層容器多少大小 [範例2](https://codepen.io/lun0223/pen/GRvByBm) 最外層的容器寫最大為 1000px,每個圖片的容器本身為 50%,所以每張圖片就會佔外層容器的一半(50%) ![](https://i.imgur.com/0dfk30T.jpg) 3. 圖片本身也要寫 max-width: 100%,這樣子可以確保圖片在不同的螢幕大小顯示都是填滿的狀態 4. 遇到這種原本圖片高度本來就不同時,就在圖片容器中寫高度 在圖片容器中寫限定的高度(比方來說 100%,佔整個外容器的高度) ![](https://i.imgur.com/S1Vs3sk.jpg) 5. 這樣子圖片的比例就會被拉壞了,所以這時候就可以用 `object-fit: cover`,這時候放大的比例就不會被拉壞,通常還會搭配 `object-position: center center (x/ y 軸的方向)`讓圖片還是會維持中心。**要注意圖片放大時,部分圖片會被裁掉。** ![](https://i.imgur.com/jqJ5LXE.jpg) ## 如果不是內文的一部分就用 `background-image` 1. 要注意 `background-iamge` 的 `width` 及 `height` 一定規範出來,要不然不會顯示圖片 2. 使用 `background-size: cover` (盡可能依照圖片容器等比例縮放,如果圖片容器大小不同時,超出的範圍圖片會被刪掉) 3. 使用 `background-position: center center(x/ y 軸的方向)`讓圖片還是維持中心 4. 使用 `background-repeat: no-repeat` 讓圖片不要重複出現 [範例3](https://codepen.io/lun0223/pen/dyzjdNR) ## 可以直接算比例 另一個方法就是使用比例來讓圖片達到 RWD 效果,常見的比例設定為 16:9,其他比例的數值可以看這裡([How TO - Aspect Ratio](https://www.w3schools.com/howto/howto_css_aspect_ratio.asp))。 1. 一樣要有外層容器(用來限制圖片區塊的大小) 2. 每個圖片也要有容器(決定每個圖片的寬度用) 3. 圖片記得要 `display: absolute` + 四個方向 0 => 全版面 **接下來在圖片容器中用 padding-bottom:(多少比例)/(多少個容器)來推圖片大小,記得圖片容器要 `display: relative` 給 `img` 抓定位。** [範例4](https://codepen.io/lun0223/pen/jOLpZXO?editors=1100) [大神的範例](https://codepen.io/adri_zag/pen/BPrejO) ### 為什麼可以用 padding hack 推圖片的大小? #### 先理解一下圖片比例的概念: ![](https://ishadeed.com/assets/aspect-ratio-css/intro-2.jpg) *可以看到 4:3 寬高的變化(寬一直是高的 0.75 倍) [ref.Let's Learn About Aspect Ratio In CSS](https://ishadeed.com/article/css-aspect-ratio/)* ![](https://ishadeed.com/assets/aspect-ratio-css/intro-3.jpg) *實際上圖,比例都維持的很好 [ref.Let's Learn About Aspect Ratio In CSS](https://ishadeed.com/article/css-aspect-ratio/)* ==由此可知,如果找到方法位置圖片及圖片容器的比例關係,那麼之後圖片便成為 responsive== #### 那有什麼方式可以限制圖片的高度呢? 這時候就是 padding hack 的進場時間。當外部容器的寬度定義完成後就剩下「制定高的比例了」,透過設定圖片容器的 `position: relative` 及 `padding-top: 比例 / 數量` 可以影響內層圖片的高度。 #### `padding-top` 不寫死的數字,用 % 是從哪裡得出 `padding-top` 的值? > % - specifies a padding in % of the width of the containing element. > [*.ref:CSS Padding*](https://www.w3schools.com/css/css_padding.asp) `padding` 不寫死使用 % 得出的數值來自元素外層容器的 width。 ![](https://ishadeed.com/assets/aspect-ratio-css/percentage-padding.jpg) *元素本身的 width 為 200px,所以 `padding-top: 50%` 便是 100px* ![](https://i.imgur.com/uwLGHPJ.png) *.testing-wrapper 的外層容器為 body,其 width 為 674px* ![](https://i.imgur.com/ubYlusY.png) *所以 .testing-wrapper 中的 `padding-top: 50%` 就是 674 / 2 = 337px* ==這也是為什麼最後在圖片的容器使用 `padding-top: 比例 / 圖片容器數量` 要除圖片容器數量,要不然 `padding-top` 會超大(因為外層 width 的緣故)== 範例架構: ```htmlembedded= <div class="card-container"> <div class="card"> <!-- 所以 image-wrapper 的 padding-top: 50% 的值是來自 .card 的 width / 2 的結果--> <div class="image-wrapper"> <img ....> </div> </div> </div> ``` 也因為 `padding-top` 按照比例擠壓圖片容器內元素的高(也就是 `img`),所以當取得 width(來自圖片容器)+`padding-top` 擠壓內部 height 再使用容器 `position: relative` 以及 `img` `position: absolute + 四方向 0`,這樣子裡面的 `img` 就會維持比例縮放了。 ## 懶得自己算的話也可以用新的 css 屬性 `aspect-ratio` `aspect-ratio: 寬的比例 / 高的比例` => `e.g. aspect-ratio: 16/9` 只要圖片容器有設定(寬/高)其中一個,之後在圖片 `img` 設定 `aspect-ratio: 寬的比例 / 高的比例` 就可以達到上方算比例的效果。 基本組合技能: ```css= .container { /* 容器提供寬度,讓 img 可以自己抓比例長大 */ width: calc(100% / 4); } img { width: 100%; aspect-ratio: 16/9; /* 額外確保圖片縮放時會有最好的效果 */ object-fit: cover; } ``` 不過這個屬性比較新,所以要注意瀏覽器支援的情況。 [CSS property: aspect-ratio](https://caniuse.com/mdn-css_properties_aspect-ratio) ## 為什麼自己算比例和用 `aspect-ratio` 圖片會自己長? 一開始我還真的不知道為什麼,結果組員一語道破:「容器提供寬/高的話,電腦就知道要怎麼算比例啦!」...原來答案這麼簡單 XDDD。 因為 `html` 的架構是容器包 `img` 的,所以如果容器有設定寬/高的話 `img` 就只能在被限定的區塊中長大 => 所以 `img` 的寬/高也就被設定了,電腦就可以算出顯示比例了。 ```htmlembedded= <div class="img-wrapper"> <img .....> </div> ``` ## 如何提升載入速度? 除了把圖片的 quality 調低之外,也可以把圖片的尺寸寫小(重要的圖片 1:2,不重要的圖片 1:1) ![](https://i.imgur.com/LD5ZHfp.jpg) 因為範例的容器是 50%(也就是 500px),所以當這個照片很重要的話就可以把該圖片的寬度裁成要顯示寬度的 2 倍。 如果這個照片不重要的話就可以裁成 (1:1)(可以看出品質有差)。 ![](https://i.imgur.com/JwtGWXr.jpg) ## 總結 1. 如果圖片不是內文的一部分,用 `<background-image>` + `background-size: cover` + `background-position: center center` + `background-repeat: no-repeat` 2. 如果圖片是內文的一部分,用 `<img>` + `object-fit: cover` + `object-position: center center` + `height: auto/ 100%` 3. 基本上第二點應該可以處理 80% 的情況 ## 參考資料 1. [網站開發「總是被忽視的圖片運用細節」 - #thef2e2021系列活動](https://www.youtube.com/watch?v=smzHWBRpfvk) => 01:00:00 - 01:15:00 2. [How to use CSS object-fit to control your images](https://www.youtube.com/watch?v=6yAAV-uP0po&t=49s) 3. [Make an Image Responsive - why is display block necessary?](https://forum.freecodecamp.org/t/make-an-image-responsive-why-is-display-block-necessary/291206) 4. [Time-saving CSS techniques to create responsive images](https://www.freecodecamp.org/news/time-saving-css-techniques-to-create-responsive-images-ebb1e84f90d5/) 5. [[教學]圖片自適應外框大小2 - 使用aspect-ratio來固定比例!](https://jameshsu0407.github.io/blog/20211130_aspect-ratio_object-fit/) 6. [Let's Learn About Aspect Ratio In CSS](https://ishadeed.com/article/css-aspect-ratio/)