用 LINE 貼圖時我有個困擾,記憶中有張超貼切的圖,但我永遠記不住它來自哪一組,作者給的關鍵字又匹配不上,只好一組一組打開來找,但最絕的是,往往全部找完一輪也沒看到,遇上傳說中的「貼圖鬼遮眼」,最後隨便找張貼圖了事。

為了解決這個困擾,我開了 Side Project,用 ASP.NET Core Minimal API 為自己寫一支桌面工具程式,從 Windows 版 LINE 抓貼圖,設計介面可為貼圖加上自訂關鍵字,這樣子,輸入關鍵字瞬間找出相關貼圖,並顯示它屬於哪一組,關鍵字可不斷微調,就不再會有找不到貼圖的困擾了。

開發過程遇到一個小問題。

查詢結果顯示框的大小是固定的,一開始沒多想,用 <img width="96" > 設成固定寬度,再配合 text-align: center 置中,但因為貼圖有大有小,有長有扁,若原本圖檔寬度小於 96px 會放大略糊,長形貼圖則會破底而出,這排版明顯不 OK。

垂直置中不難,我查到以下萬用置中寫法:

.sticker img {
    position: absolute;
    top: 50%; left: 50%;
    transform: translate(-50%, -50%);
}

至於長寬縮放,硬綁綁的程式腦很自然地想到用程式解決:

document.querySelectorAll('.sticker img').forEach(function(img) { 
    if (img.naturalHeight > img.naturalWidth) 
        img.setAttribute('height', '96');
    else 
        img.setAttribute('width', '96');
});

這招果然管用。(實際程式比這複雜許多,因為我用 Vue.js 產生結果項目,需抓對執行時機調尺寸,甚至還為此寫了自訂元件 <auto-size-img v-bind:src='...' >)

雖然用程式解決了,但總覺有點殺雞用牛刀,應該有 CSS 方法可以優雅搞定才對。

爬文學到新樣式 - object-fit,可以決定 <img> 或 <video> 如何依容器調整大小。共有五個選項:

  • fill: 不管原圖比例,縮放成容器的寬度及高度
  • contain: 依容器長寬限制依原始比例縮放圖片,以不超過高度或寬度顯示最大完整內容。
  • cover: 依容器長寬限制依原始比例縮放圖片,儘可能佔滿容器寬度「或」高度為原則,超出容器部分會被截掉
  • none: 不縮放,顯示原圖
  • scale-down: 只縮不放,行為比照 contain(若圖片大於容器) 或 none(若圖片小於容器)

(如果覺得以上解釋太抽象,MDN 有互動展示)

.sticker img {
    position: absolute;
    top: 50%; left: 50%;
    transform: translate(-50%, -50%);
    width: 100px; height: 100px;
    object-fit: scale-down;
}

這樣,不用寫半行程式便得到完全相同的效果。針對設定上限只縮不放的狀況,我發現還有另一種寫法,設定 max-width、max-height 也有相同效果。但如果圖片偏小要放大,object-fit: contain 是較佳選擇。

.sticker img {
    position: absolute;
    top: 50%; left: 50%;
    transform: translate(-50%, -50%);
    max-width: 100px; max-height: 100px;
}

再學到 CSS 小技巧一則,Side Project 真是程式設計師的少林木人街,增加功力的好地方。

[2022-04-18 更新] 讀者許意明補充好用雙向置中 CSS 技巧 - object-position: center center(特此感謝),可取代原本囉嗦的 postion、top、transform 寫法,而且它是預設值可省略不寫。 (又一次拋磚引玉)

.sticker img {
    object-position: center center; /* 預設值即為 center center,此行可省 */
    object-fit: scale-down;
    width: 100px; height: 100px;
}

Tips of how to use CSS style to certer image horizontally and vertically, and auto-resize to fit container.


Comments

# by Not

Conver應該是cover,看來是太開心拼錯字了😂 另外提供一些心得,使用cover如同說明會縮放,但如原始圖片與要呈現的框框長寬比例不同,有可能會裁掉一部分 例如16:9橫的人物照片放到正方形的框,可能會變成取中間兩個人都沒入鏡的悲劇畫面,使用前請先考量原始圖片來源

# by Jeffrey

to Not,謝謝指正跟補充。cover 已補上圖片可能被裁掉的說明。

# by eric

其實大家都有這個困擾,可以敲碗成品嗎?

Post a comment