镜像站点 · 本页由第三方 GitHub 只读镜像提供,非 GitHub 官方站点,不接受任何登录或凭据输入。前往 github.com
Skip to content

谈谈一些有趣的CSS题目(2)-- 条纹边框的多种实现方式 #1

Open

Description

@chokcoco

开本 issues ,讨论一些有趣的 CSS 题目,抛开实用性而言,一些题目为了拓宽一下解决问题的思路,此外,涉及一些容易忽视的 CSS 细节。

解题不考虑兼容性,题目天马行空,想到什么说什么,如果解题中有你感觉到生僻的 CSS 属性,赶紧去补习一下吧。

不断更新,不断更新,不断更新,重要的事情说三遍。

2、类似下面这个图形,只使用一个标签,可以有多少种实现方式:

image

假设我们的单标签为 div:

<div></div>

定义如下通用 CSS:

div{
    position:relative;
    width: 180px;
    height: 180px;
}

这一题主要考查的是盒子模型 Box Model 与 背景 background 的关系,以及使用 background-clip 改变背景的填充方式。

background 在 Box Model 中,他是布满整个元素的盒子区域的,并不是从 padding 内部开始(也就是说从 border 就开始啦),只不过实线边框(solid)部分遮住了部分 background ,所以我们使用虚线边框(dashed)就可以看到背景色是从 border 内部开始的。

我们给 div 添加如下样式:

div{
    background:#9c27b0;
    border:20px dashed #2196f3;
}

结果如下:

image

但有一点需要注意,background-color 是从元素的边框左上角起到右下角止,而 background-image 却不一样,他是从 padding 边缘的左上角起而到 border 的右下角边缘止。

background image 的绘制中有两个因素决定了绘图区域:

  1. background positioning area。background-origin 属性决定了这个相对定位位置,默认为 padding-box。所以默认的背景图片绘制是从 padding box 的左上顶点开始的。
  2. background painting area。background-clip 属性决定了绘制区间,默认为 border-box。所以在 background-repeat: repeat 的情况下:

The image is repeated in this direction as often as needed to cover the background painting area.

嗯,什么意思呢,你可以戳进这个 demo 看看,正常情况下的背景图填充如下:

image

当然,这个填充规则是可以通过 background-clip 改变的。

background-clip 设置元素的背景(背景图片或颜色)是否延伸到边框下面。

语法:

background-clip: border-box;  // 背景延伸到边框外沿(但是在边框之下)
background-clip: padding-box; // 边框下面没有背景,即背景延伸到内边距外沿。
background-clip: content-box; // 背景裁剪到内容区 (content-box) 外沿。

继续说回本题,接下来,只需要将中间部分填充为白色即可,这个用伪元素可以轻松完成,所以,其中一个方法如下:

div{
    background:#9c27b0;
    border:20px dashed #2196f3;
}
div::after{
    content:"";
    position:absolute;
    top:0;
    left:0;
    bottom:0;
    right:0;
    background:#fff;
}

法二:

上面的方法,我们使用了 div 的背景色默认情况下从 border 开始填充,及伪元素设置白色背景色填充 div 的中间的 padding-box 区域完成图形。

也可以反过来,使用伪元素背景色从 border-box 开始填充,使用 div 的背景色填充中间 padding-box区域。

div{
    background:#fff;
    background-clip:padding-box;
    border:20px dashed #cccc99;
}
div::before{
    content:"";
    position:absolute;
    top:-20px;
    left:-20px;
    bottom:-20px;
    right:-20px;
    background:#996699;
    z-index:-1;
}

具体的 Demo 戳这里 。

上面 法二 除了用到了 background-clip 改变背景的填充区域,还用到了 z-index 触发元素生成了堆叠上下文(stacking context),改变了元素的层叠顺序(stacking levle),让伪元素背景色叠到了 div 背景色 之下,这两个概念下题会提及。

法....

本题主要是想讨论一下 CSS 的盒子模型 Box Model 与 背景 background 的关系,其实本题就是在于一个 dashed 边框,内部使用颜色填充即可,与上面第一题异曲同工,使用阴影、渐变都可以完成,感兴趣可以自己尝试一下其他解法。

Activity

  1. dolphin-wood commented on Sep 19, 2016

    @dolphin-wood

    background-image 默认也是从 border-box 延展开的:

    2016-09-19 19 40 22

  2. feilongcheng commented on Sep 19, 2016

    @feilongcheng

    +1

  3. chokcoco commented on Sep 19, 2016

    @chokcoco
    OwnerAuthor

    @idiotWu
    刚刚没看清楚就瞎回复了,见谅。
    看你图中的确实是从 border 开始的,有demo吗,我这边的demo都是从
    paading-box 开始的。
    CssBackground

  4. dolphin-wood commented on Sep 19, 2016

    @dolphin-wood

    @chokcoco
    查了相关的标准,发现原因在于你设定了 background-repeat: no-repeat。

    background image 的绘制中有两个因素决定了绘图区域:

    1. background positioning area。background-origin 属性决定了这个相对定位位置,默认为 padding-box。所以默认的背景图片绘制是从 padding box 的左上顶点开始的。
    2. background painting area。background-clip 属性决定了绘制区间,默认为 border-box。所以在 background-repeat: repeat (default)的情况下:

    The image is repeated in this direction as often as needed to cover the background painting area.

  5. chokcoco commented on Sep 19, 2016

    @chokcoco
    OwnerAuthor

    @idiotWu
    感谢提出,我正好也在查看标准是怎么定义的,我补充到题中去。

  6. feilongcheng commented on Sep 23, 2016

    @feilongcheng

    嗯 吹毛求疵一下。
    第四题的法2为什么不直接用rotateX = =

  7. changed the title [-]谈谈一些有趣的CSS题目[/-] [+]谈谈一些有趣的CSS题目(1~5)[/+] on Sep 23, 2016
  8. chokcoco commented on Sep 23, 2016

    @chokcoco
    OwnerAuthor

    @wangpengfei15975
    厉害了我的哥,两个写法确实是一样的,rotateX 应该是更简洁的。

  9. evensandbox commented on Oct 22, 2016

    @evensandbox

    第五个, 已经用了 flex box, 可以直接在侧轴方向上居中. DEMO

  10. Serena211 commented on Oct 22, 2016

    @Serena211

    sorry, 刚刚发错地方了。第二个dashed border box 的outline解法

    .style_outline {
    &::before{
    content:"";
    position:absolute;
    top:0;
    left:0;
    bottom:0;
    right:0;
    outline:20px solid #ffc107;
    background:#fff;
    z-index:-1;
    }
    感觉这样更合理一点。

  11. bytemofan commented on Oct 25, 2016

    @bytemofan

    非常有意思

  12. jiangxiaolin1995 commented on Nov 3, 2016

    @jiangxiaolin1995

    啊哈,脑洞好大啊

  13. OnionStu commented on Dec 1, 2016

    @OnionStu

    第5题,如果加上点击加载更多呢…要如何实现?

  14. github302 commented on Dec 7, 2016

    @github302

    第1题,当用border-left设置样式的时候,div的整个宽度就会加长,如果想要div整体宽度不变的话,就需要加上box-sizing:border-box;
    使用外 box-shadow的时候div宽度也会加长,内 box-shadow就不会,所以如果需求还要保证div整体宽度不变的话,得注意下这些点。

    `.demo1 {
    position:relative;
    width:200px;
    height:60px;
    background:#ddd;
    }

    .demo2 {
    position:relative;
    width:200px;
    height:60px;
    background:#ddd;
    }

    .demo2:after {
    position:absolute;
    left:0;
    top:0;
    content:'';
    width:5px;
    height:60px;
    background: deeppink;
    }

    .demo3 {
    position:relative;
    width:200px;
    height:60px;
    background:#ddd;
    box-shadow: inset 5px 0 0 deeppink;
    }

    .demo4 {
    position:relative;
    width:200px;
    height:60px;
    background:#ddd;
    border-left:solid 5px deeppink;
    box-sizing:border-box;
    }
    .demo5 {
    position:relative;
    width:200px;
    height:60px;
    background:#ddd;
    box-shadow:-5px 0 0 deeppink;
    }
    .demo6 {
    position:relative;
    width:200px;
    height:60px;
    background:#ddd;
    border-left:solid 5px deeppink;
    }







    ` 可以对比看下容器宽度
  15. olovey commented on Mar 23, 2017

    @olovey

    好厉害啊,刚入前端,真的学习到很多。谢谢

  16. 3 remaining items

  17. jokum commented on Aug 31, 2017

    @jokum

    第一个:不知道用背景图片(repeat-y)算不算

  18. llqkl commented on May 15, 2018

    @llqkl

    专门注册了来问一下,为什么第二题的法一,我得到的结果是这样的呢,边框从左上角开始,但是是连着的,不是左上角一个小方块那种
    qq 20180515104238

  19. Jemair commented on Aug 15, 2018

    @Jemair

    关于移动端多行省略 我这里有个更好的实现
    https://codepen.io/isjemair/pen/oMRZvm
    切换最外层的folded类名就可以实现查看更多和收起状态

    法一的实现不能实现点击查看更多
    法二的实现很容易造成文字被截一半

    原本的方法是在网上找到一个老外的 我在做的时候是把其中的参数抽出来作为变量

  20. huan-joy commented on Aug 17, 2018

    @huan-joy

    关于前两个问题,其实还可以直接用img标签嘛(要是说不能包含外部图片,可以把图片转成base64编码嘛),同理还可以使用svg标签嘛。

  21. zsjun commented on Oct 10, 2018

    @zsjun

    image

    专门注册了来问一下,为什么第二题的法一,我得到的结果是这样的呢,边框从左上角开始,但是是连着的,不是左上角一个小方块那种
    qq 20180515104238
    我的也是,感觉是lz写法有问题

  22. chokcoco commented on Oct 10, 2018

    @chokcoco
    OwnerAuthor

    @zsjun 我尝试了下现版本的chrome下确实是上图你发的效果。
    因为写这个这篇文章的时间距离现在有一段时间了,我再去确认考究下,再给你个答复~

  23. zsjun commented on Oct 11, 2018

    @zsjun

    @zsjun 我尝试了下现版本的chrome下确实是上图你发的效果。
    因为写这个这篇文章的时间距离现在有一段时间了,我再去确认考究下,再给你个答复~

    好的,多谢,我用的是goole浏览器的69.0.3497.100版本,最新的版本

  24. mask2012 commented on Oct 12, 2018

    @mask2012

    关于移动端多行省略 我这里有个更好的实现
    https://codepen.io/isjemair/pen/oMRZvm
    切换最外层的folded类名就可以实现查看更多和收起状态

    法一的实现不能实现点击查看更多
    法二的实现很容易造成文字被截一半

    原本的方法是在网上找到一个老外的 我在做的时候是把其中的参数抽出来作为变量

    @Jemair 你的demo的问题是展开是用颜色盖在上边的,所以底部背景变化,或不是纯色会露出马脚
    image

  25. spadek-w commented on Oct 19, 2018

    @spadek-w

    第3个父元素 display: flex;flex-direction: row-reverse; 子元素margin-left:负值 好像也行

  26. wd2010 commented on Nov 9, 2018

    @wd2010

    大神你好,这些思考非常值得学习。关于第2道思考题我在backgroun-image和background-color上有点疑惑想请教下。下图是我通过伪元素实现的,但我想通过background-image的多背景实现,内部的background-image的终止点总是在border右下角,我想把它终止点在padding右下角,请问可以怎么实现呢?
    1111111111

    以下是我想实现的代码,但不起作用

    div{
          margin:20px;
          width: 400px;
          height:400px;
          border: 10px dashed green;
          padding: 20px;
          background-repeat: no-repeat, no-repeat;
          background-image:
              url(./img/1.jpg),
              linear-gradient(to right, red,red);
          background-clip: padding-box, border-box;
        }
  27. weijiyang commented on Dec 31, 2018

    @weijiyang

    "嗯,什么意思呢,你可以戳进这个 demo 看看,正常情况下的背景图填充如下" 感觉这个demo里面的和后面加菲猫配图讲解的不太相符 代码中background-clip 默认都是border-box 在border之下 但是加菲猫图片说背景图是padding左上角到border 右下角 还是我的理解有问题?

  28. changed the title [-]谈谈一些有趣的CSS题目(1~5)[/-] [+]谈谈一些有趣的CSS题目(2)-- 条纹边框的多种实现方式[/+] on Mar 18, 2019
  29. gentlecoder commented on Apr 26, 2019

    @gentlecoder
    background-image: linear-gradient(to left,white,white);
    background-repeat: no-repeat;
    

    直接在div加上这两个样式好像也行

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions