iT邦幫忙

2019 iT 邦幫忙鐵人賽

DAY 27
1
Modern Web

CSS Secrets 導讀系列 第 27

Secret 21: 用CSS換行

  • 分享至 

  • twitterImage
  •  

需要用CSS換行的時機通常是在使用definition lists的時候,但有時在其他的場合也會有同樣需求。會使用definition lists因為我們想做一個良好的網路公民,所以使用適當、有語意的標記語言,即使在視覺上需要的其實是項目名稱和內容的配對組合。例如下面這段標記語言結構:

<dl>
	<dt>Name:</dt>
	<dd>Joaquin Phoenix</dd>

	<dt>Born:</dt>
	<dd>October 28, 1974</dd>

	<dt>Filmography:</dt>
	<dd>Her</dd>
</dl>

https://ithelp.ithome.com.tw/upload/images/20181111/20091606pSgnccBAyL.png
(原生的definition lists樣式)

通常我們會想要的是項目名稱在左,項目內容在右,新的項目在下一行。所以我們可能會加入以下的CSS:

dd {
	margin: 0;
	font-weight: bold;
}

https://ithelp.ithome.com.tw/upload/images/20181111/200916063Bbe4Nap1F.png

然而因為<dt><dd>都是block元素,上面的樣式只是減少了縮排,清單裡的每個項目仍然單獨在一行。

接著我們可能會試試看變更<dt><dd>display屬性,然後搞得一團亂。(你來試試看)

https://ithelp.ithome.com.tw/upload/images/20181111/20091606wygxaHTWbv.png
(設成inline全部都連在一起了)

除了抱怨CSS不夠力,在一切絕望只剩下調整HTML結構這個大絕之前,有沒有方法能讓我們同時保持理性和有條理的HTML結構呢?


基本上,我們需要在每一個<dd>的後面加上換行標記,如果不在意HTML語意的話,用<br>就行。

<dl>
	<dt>Name:</dt>
	<dd>Joaquin Phoenix<br /></dd>
</dl>

然後為<dt><dd>加上display: inline就OK了。當然,這不只在維護上是不好的做法,同時也讓我們的結構變大了。如果可以用自動產生的內容來加上換行標記,我們就解決問題了!有這樣的東西嗎?

有一個Unicode符號和換行標記的0x000A相同,在CSS裡寫做\000A,或是簡寫成\A。如果我們在<dd>的偽元素::after裡加入這個符號是不是就能自動換行了?

dd::after {
	content: "\A";
}

結果卻是一點反應也沒有,是哪裡出了問題?原因出在偽元素是放在<dd>裡面,在HTML裡,所有換行都是被忽略的,所以我們的方法也被視為是一般的換行而被無視掉。要保留空白和換行的話,會使用white-space: pre;。我們也可以這麼做。

dt, dd { display: inline; }

dd {
	margin: 0;
	font-weight: bold;
}

dd::after {
	content: "\A";
	white-space: pre;
}

https://ithelp.ithome.com.tw/upload/images/20181111/20091606jhb481oEcd.png

這下子得到我們要的效果了,不過它夠彈性嗎?在演員參與過的作品再加入一部電影會發生什麼事?

<dl>
	<dt>Filmography:</dt>
	<dd>Her</dd>
	<dd>Joker</dd>
</dl>

https://ithelp.ithome.com.tw/upload/images/20181111/200916066tDMQJMGQy.png

新加入的電影換到新的一行去了,因為每一個<dd>都加入了換行符號的關係。如果同一個項目的內容都能在一行,以逗點隔開就好了。

所以我們應該只要找出任何在<dt>前面一個的<dd>,換行符號加在這些<dd>上就可以了。可是用過CSS的人都知道,CSS的選擇器只能選取後面的元素,不能向前選,我們要找另一個方法。其中之一是與其把換行符號加在dd::after,試試看加在dt::before

dt::before {
	content: "\A";
	white-space: pre;
}

https://ithelp.ithome.com.tw/upload/images/20181111/200916064ssoLHxb2J.png

不過這樣子就讓第一個項目前面多了空行,讓我們再試試更多的選擇方法:

  • dt:not(:first-child)
  • dt ~ dt
  • dd + dt

我們決定用最後一種,因為如果一個值有多個<dt>時它仍然可以用。

最後要在不同的內容之間加上逗號和空格,直覺上會希望「當<dd>後面也有<dd>時,為前面那個加上逗號」,不過CSS是不能選擇之前的元素,我們只能改變方法,在二個連續的<dd>情況下,給後面那個的::before偽元素加入逗號。

dd + dt::before {
	content: "\A";
	white-space: pre;
}

dd + dd::before {
	content: ", ";
	font-weight: normal;
}	

https://ithelp.ithome.com.tw/upload/images/20181111/20091606WoR6hKDcdQ.png

CodePen


上一篇
Secret 19: 折角效果2
下一篇
Secret 22: 斑馬條紋
系列文
CSS Secrets 導讀30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言