在CSS中經常會用到對一個元素進行變換(Transform)但希望元素的內容保持不變的效果;但當我們對元素進行變換時,得到的效果是:不但背景被變換了,而且內容也被變換了;示例如下:
以skewX()變換為例,假設有以下元素:
HTML結構:
<p>
我是內容
</p>
css樣式:
p {
display: inline-block;
border-color: red;
border-width:1px;
border-style: solid;
}
效果:
如果對這個元素使用skewX()變換,則會得到如下效果:
CSS樣式:
transform: skewX(45deg);
效果:
從效果中可以看出,不僅元素的背景被變換了,而且里面的內容也被變換了,然而,在很多場景下我們只希望變換背景,內容保持不變;
若要解決這個問題,也有多種方案可選(推薦方案3喲),如下:
方案1:外套元素
原理:
在變換時,為了把背景樣式與元素內容分離,可以把目標元素嵌入在一個容器元素內,比如div元素,然后把目標元素的背景樣式移動到容器元素上,使容器元素僅負責背景樣式(稱僅負責樣式的元素為樣式元素),目標元素僅負責內容;然后對樣式元素進行變換,再對目標元素進行反向變換,這樣便實現了變換了背景樣式,而又還原了內容;
原理演示:
-
給目標元素添加一個容器元素作為樣式元素;
** HTML結構:**<div> <p> 我是內容 </p> </div>
-
把目標元素的背景樣式移動到容器元素上;
示例效果:
外套元素.png注意:
虛線框只是用來標識元素的存在,并不表示元素的樣式; -
對容器元素應用變換;
CSS樣式:transform: skewX(45deg);
示例效果:
外套元素-變換.png -
對目標元素應用反向變換;
CSS樣式:transform: skewX(-45deg);
示例效果:
外套元素-糾正.png
此方案優點:
- 原理直觀,易理解;
- 可以實現任意多樣式及內容的分離;
- 需要對目標內容再進行反向變換;(有此變換操作是不可逆的,所以反向變換會可能不能還原效果;)
此方案缺點:
- 添加了較多冗余的元素;
方案2:內嵌元素
原理:
與外套元素的方案類似,只是把樣式元素插入到了目標元素里面,作為了目標元素的子元素;這樣,在對樣式元素進行變換時,不會影響到目標元素的內容,從而不用使用反向變換;
原理演示:
-
給目標元素添加一個子元素作為樣式元素;
** HTML結構:**<p> <span></span> 我是內容 </p>
-
把目標元素的背景樣式移動到樣式元素上;
示例效果:
內嵌元素.png注意:
- 虛線框只是用來標識元素的存在,并不表示元素的樣式;
- 如果樣式元素遮擋了目標元素的內容,則需要給樣式元素設置合適的層疊級別z-index;
-
對樣式元素應用變換;
CSS樣式:transform: skewX(45deg);
示例效果:
內嵌元素-變換.png
此方案優點:
- 原理直觀,易理解;
- 可以實現任意多樣式及內容的分離;
- 不用對目標內容再進行反向變換;
此方案缺點:
- 添加了較多冗余的元素;
方案3:前后偽元素
原理:
與內嵌元素方案的原理一樣,所不同的是:本方案采用偽元素::before或者::after來作為樣式元素,而不是另外插入額外的元素;
原理演示:
以::before偽元素為例:
-
把目標元素的樣式應用到其偽元素::before上;
** CSS樣式:**p::before { border-color: red; border-width:1px; border-style: solid; }
-
調整::before偽元素的盒子使其與目標元素盒子重疊;
因為在::before和::after偽元素選擇器中必須定義content屬性,所以需要為::before選擇器中設置值為空字符串的content屬性;
另外,因為瀏覽器會為這2個偽元素選擇器分別生成相應的盒子,并且這些盒子是作為元素的非主盒子,所以為了不影響主盒子(目標元素的內容)的布局,需要:- 讓偽元素脫離正常文檔流;
- 讓目標元素的主盒子成偽元素盒子的包含塊;
所以需要
- 給目標元素設置樣式
position: relative;
- 給偽元素::before設置樣式:
position: absolute; width: 100%; height: 100%;
最終,示例代碼如下:
** HTML結構:**<p> 我是內容 </p>
CSS樣式:
p { display: inline-block; position: relative; /*為::before偽元素生成包含*/ } p::before { content: ''; position: absolute; /*脫離文檔流*/ width: 100%; height: 100%; /*目標元素的樣式*/ border-color: red; border-width:1px; border-style: solid; }
示例效果:
偽元素.png注意:
- 虛線框只是用來標識元素的存在,并不表示元素的樣式;
- 如果樣式元素遮擋了目標元素的內容,則需要給樣式元素設置合適的層疊級別z-index;
-
對::before偽元素應用變換;
CSS樣式:transform: skewX(45deg);
示例效果:
偽元素-變換.png
此方案優點:
- 原理直觀,易理解;
- 不用對目標內容再進行反向變換;
- 不用添加冗余元素;
此方案缺點:
- 只能把樣式及內容分離成2個獨立的部分,不對分成3個或者更多的獨立部分;
相關文章:《 CSS中特殊效果的實現方案》