chokcoco / iCSS

不止于 CSS

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

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

chokcoco opened this issue · comments

commented

开本 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 边框,内部使用颜色填充即可,与上面第一题异曲同工,使用阴影、渐变都可以完成,感兴趣可以自己尝试一下其他解法。

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

2016-09-19 19 40 22

commented

+1

commented

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

@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.

commented

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

commented

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

commented

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

commented

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

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

非常有意思

啊哈,脑洞好大啊

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

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







` 可以对比看下容器宽度

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

commented

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

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

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

commented

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

commented

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

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

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

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

commented

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

commented

image

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

commented

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

commented

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

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

commented

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

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

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

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

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

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

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

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

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