Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
chokcoco opened this issue Sep 19, 2016 · 29 comments

Comments

@chokcoco
Copy link
Owner

chokcoco commented Sep 19, 2016

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

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

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

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

image

假设我们的单标签为 div:

<div></div>

定义如下通用 CSS:

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

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

backgroundBox 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 areabackground-origin 属性决定了这个相对定位位置,默认为 padding-box。所以默认的背景图片绘制是从 padding box 的左上顶点开始的。
  2. background painting areabackground-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 边框,内部使用颜色填充即可,与上面第一题异曲同工,使用阴影、渐变都可以完成,感兴趣可以自己尝试一下其他解法。

@idiotWu
Copy link

idiotWu commented Sep 19, 2016

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

2016-09-19 19 40 22

@wangpengfei15975
Copy link

+1

@chokcoco
Copy link
Owner Author

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

@idiotWu
Copy link

idiotWu commented Sep 19, 2016

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

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

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

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

@chokcoco
Copy link
Owner Author

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

@wangpengfei15975
Copy link

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

@chokcoco chokcoco changed the title 谈谈一些有趣的CSS题目 谈谈一些有趣的CSS题目(1~5) Sep 23, 2016
@chokcoco
Copy link
Owner Author

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

@zhanhongtao
Copy link

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

@Serena211
Copy link

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;
}
感觉这样更合理一点。

@bytemofan
Copy link

非常有意思

@jiangxiaolin1995
Copy link

啊哈,脑洞好大啊

@OnionStu
Copy link

OnionStu commented Dec 1, 2016

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

@github302
Copy link

第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;
}







` 可以对比看下容器宽度

@olovey
Copy link

olovey commented Mar 23, 2017

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

@chokcoco
Copy link
Owner Author

@olovey
建议去我的博客读这些文章,可以看到Demo,效果更好,github没办法嵌入iframe。

@desperadoray
Copy link

  1. 法3 [code] box-shaodw -> shadow

@wmh1106
Copy link

wmh1106 commented Jul 28, 2017

第四题:如果是倒影,还可以用缩放来做的scale
demo

@jokum
Copy link

jokum commented Aug 31, 2017

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

@llqkl
Copy link

llqkl commented May 15, 2018

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

@Jemair
Copy link

Jemair commented Aug 15, 2018

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

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

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

@huan-joy
Copy link

huan-joy commented Aug 17, 2018

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

@zsjun
Copy link

zsjun commented Oct 10, 2018

image

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

@chokcoco
Copy link
Owner Author

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

@zsjun
Copy link

zsjun commented Oct 11, 2018

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

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

@mask2012
Copy link

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

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

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

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

@spadek-w
Copy link

spadek-w commented Oct 19, 2018

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

@wd2010
Copy link

wd2010 commented Nov 9, 2018

大神你好,这些思考非常值得学习。关于第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;
    }

@weijiyang
Copy link

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

@chokcoco chokcoco changed the title 谈谈一些有趣的CSS题目(1~5) 谈谈一些有趣的CSS题目(2)-- 条纹边框的多种实现方式 Mar 18, 2019
@gentlecoder
Copy link

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
Projects
None yet
Development

No branches or pull requests