CSS中变换背景保持内容的实现方案

在CSS中经常会用到对一个元素进行变换(Transform)但希望元素的内容保持不变的效果;但当我们对元素进行变换时,得到的效果是:不但背景被变换了,而且内容也被变换了;示例如下:

以skewX()变换为例,假设有以下元素:
HTML结构:

<p>
    我是内容
</p>

css样式:

p {
    display: inline-block;
    border-color: red;
    border-width:1px;
    border-style: solid;
}

效果:

示例效果.png

如果对这个元素使用skewX()变换,则会得到如下效果:
CSS样式:

transform: skewX(45deg);

效果:

示例效果-变换.png

从效果中可以看出,不仅元素的背景被变换了,而且里面的内容也被变换了,然而,在很多场景下我们只希望变换背景,内容保持不变;

若要解决这个问题,也有多种方案可选(推荐方案3哟),如下:

方案1:外套元素

原理:

在变换时,为了把背景样式与元素内容分离,可以把目标元素嵌入在一个容器元素内,比如div元素,然后把目标元素的背景样式移动到容器元素上,使容器元素仅负责背景样式(称仅负责样式的元素为样式元素),目标元素仅负责内容;然后对样式元素进行变换,再对目标元素进行反向变换,这样便实现了变换了背景样式,而又还原了内容;

原理演示:

  1. 给目标元素添加一个容器元素作为样式元素;
    ** HTML结构:**

    <div>
        <p>
            我是内容
        </p>
    </div>
    
  2. 把目标元素的背景样式移动到容器元素上;
    示例效果:

    外套元素.png

    注意:
    虚线框只是用来标识元素的存在,并不表示元素的样式;

  3. 对容器元素应用变换;
    CSS样式:

    transform: skewX(45deg);
    

    示例效果:

    外套元素-变换.png

  4. 对目标元素应用反向变换;
    CSS样式:

    transform: skewX(-45deg);
    

    示例效果:

    外套元素-纠正.png

此方案优点:

  1. 原理直观,易理解;
  2. 可以实现任意多样式及内容的分离;
  3. 需要对目标内容再进行反向变换;(有此变换操作是不可逆的,所以反向变换会可能不能还原效果;)

此方案缺点:

  1. 添加了较多冗余的元素;

方案2:内嵌元素

原理:

与外套元素的方案类似,只是把样式元素插入到了目标元素里面,作为了目标元素的子元素;这样,在对样式元素进行变换时,不会影响到目标元素的内容,从而不用使用反向变换;

原理演示:

  1. 给目标元素添加一个子元素作为样式元素;
    ** HTML结构:**

    <p>
        <span></span>
        我是内容
    </p>
    
  2. 把目标元素的背景样式移动到样式元素上;
    示例效果:

    内嵌元素.png

    注意:

    1. 虚线框只是用来标识元素的存在,并不表示元素的样式;
    2. 如果样式元素遮挡了目标元素的内容,则需要给样式元素设置合适的层叠级别z-index;
  3. 对样式元素应用变换;
    CSS样式:

    transform: skewX(45deg);
    

    示例效果:

    内嵌元素-变换.png

此方案优点:

  1. 原理直观,易理解;
  2. 可以实现任意多样式及内容的分离;
  3. 不用对目标内容再进行反向变换;

此方案缺点:

  1. 添加了较多冗余的元素;

方案3:前后伪元素

原理:

与内嵌元素方案的原理一样,所不同的是:本方案采用伪元素::before或者::after来作为样式元素,而不是另外插入额外的元素;

原理演示:

以::before伪元素为例:

  1. 把目标元素的样式应用到其伪元素::before上;
    ** CSS样式:**

    p::before {
        border-color: red;
        border-width:1px;
        border-style: solid;
    }
    
  2. 调整::before伪元素的盒子使其与目标元素盒子重叠;
    因为在::before和::after伪元素选择器中必须定义content属性,所以需要为::before选择器中设置值为空字符串的content属性;
    另外,因为浏览器会为这2个伪元素选择器分别生成相应的盒子,并且这些盒子是作为元素的非主盒子,所以为了不影响主盒子(目标元素的内容)的布局,需要:

    1. 让伪元素脱离正常文档流;
    2. 让目标元素的主盒子成伪元素盒子的包含块;

    所以需要

    1. 给目标元素设置样式position: relative;
    2. 给伪元素::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

    注意:

    1. 虚线框只是用来标识元素的存在,并不表示元素的样式;
    2. 如果样式元素遮挡了目标元素的内容,则需要给样式元素设置合适的层叠级别z-index;
  3. 对::before伪元素应用变换;
    CSS样式:

    transform: skewX(45deg);
    

    示例效果:

    伪元素-变换.png

此方案优点:

  1. 原理直观,易理解;
  2. 不用对目标内容再进行反向变换;
  3. 不用添加冗余元素;

此方案缺点:

  1. 只能把样式及内容分离成2个独立的部分,不对分成3个或者更多的独立部分;

相关文章:CSS中特殊效果的实现方案

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 问答题47 /72 常见浏览器兼容性问题与解决方案? 参考答案 (1)浏览器兼容问题一:不同浏览器的标签默认的外补...
    _Yfling阅读 13,800评论 1 92
  • 本文转载自:众成翻译译者:为之漫笔链接:http://www.zcfy.cc/article/239原文:http...
    极乐君阅读 7,403评论 1 62
  • 一:在制作一个Web应用或Web站点的过程中,你是如何考虑他的UI、安全性、高性能、SEO、可维护性以及技术因素的...
    Arno_z阅读 1,212评论 0 1
  • 又叫马儿跑 又叫马儿不吃草
    林下生风阅读 1,275评论 7 15
  • "目录号: HY-14184A GPCR/G Protein- Macitentan丁基类似物是Macitenta...
    莫小枫阅读 123评论 0 0