CSS 的扩展边框

Extended borders with CSS

我一直在用一些嵌套的 div 测试 extended/projecting 边框的想法,我在下面有一个工作示例。

基本上,我想要实现的是延伸到盒子外面的垂直和水平边框,盒子里面有内容。有点像起草的样子。如果可能的话,我希望它能够完全响应。

在我的代码中,我设置了带负边距的高度,以便在视觉上获得我想要的效果,但看起来我的标记对于我想要做的事情来说太臃肿了。它在水平方向上 响应,但在垂直方向上我只是隐藏了溢出。

我在做这个的时候想到的另一个想法是有 4 个 divs,每个边界边 1 个(上、右、下、左),然后每个 div 偏移一个一定量才能达到效果。有点像 "jiggled" 的 div 簇。 4 div 将由父容器携带并响应。

这能比我在 fiddle 中做的更简单吗?有没有办法让它在垂直方向和水平方向都灵活(完全响应)?是否可以对每个边框边进行可变扩展(例如一侧为 2px,另一侧为 4px)?

废话少说,下面是我目前的情况:

body {
  margin: 0;
  padding: 0;
  width: 100%;
  font-family: Helvetica, Arial, sans-serif;
  /* text-align: center; */
}

.container {
  margin: 50px auto 0;
  padding: 0;
  width: 75%;
  height: 200px;
  position: relative;
}

.box-vert {
  margin: -10px 0;
  padding: 0;
  overflow: visible;
  height: 200px;
  position: absolute;
  border: 1px solid #C5C5C5;
  border-top: none;
  border-bottom: none;
}

.box-horz {
  height: 180px;
  margin: 10px -10px;
  overflow: visible;
  border: 1px solid #C5C5C5;
  border-left: none;
  border-right: none;
  padding: 0;
}

.box-inner {
  margin: 0 10px;
  padding: 20px;
  background-color: #ECECEC;
  height: 140px;
  float: left;
  overflow: hidden;
}

.box-inner h1 {
  margin: 0 0 10px;
  text-transform: uppercase;
  font-weight: 200;
  letter-spacing: 3px;
  font-size: 30px;
  color: #009688;
}

.box-inner p {
  margin: 0;
  line-height: 1.4;
  font-size: 14px;
  color: #666;
}
<div class="container">
  <div class="box-vert">
    <div class="box-horz">
      <div class="box-inner">
        <h1>Title Text Here</h1>
        <p>Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Cras mattis consectetur purus sit amet fermentum. Praesent commodo cursus magna, vel scelerisque nisl consectetur et. Vestibulum id ligula porta felis euismod semper.</p>
      </div>
    </div>
  </div>
</div>

您可以使用单个元素和背景渐变来执行此操作,如下面的代码段所示。输出是响应式的(正如您在完整页面视图中看到的那样)并且可以根据内容的大小自行调整。

该方法有点复杂,因为它是用单个元素完成的,所以这里有一个解释:

  • 向元素的所有边添加 15px 的填充,以将文本流限制在较小的区域(即,在我们要创建的边框内)。
  • 添加了 4 个线性渐变背景图像(每个边框一张),并设置它们的背景大小,使每个边框的厚度为 1px,但 width/height 为 100%。
  • 对于顶部和底部边框,thickness/height 为 1px(或任何我们需要的)并且边框的宽度将与容器的宽度相同,因此 background-size 设置为 100% 1px.
  • 对于左右边框,thickness/width为1px,高度为容器高度的100%,所以background-size设置为1px 100%
  • 然后定位这些渐变线,使它们在父级内偏移。也就是说,上边框应该在 y 轴上偏移 10px(或者任何我们需要的,但它应该小于 padding),左边框应该在 x 轴上偏移 10px。类似地,底部和右边框应该从容器的底部和右边缘偏移 10px,因此 calc 函数用于定位它们。
  • 对于元素的背景,我们不能使用这种方法使用简单的 background-color,因为它会填满整个 div(超出边界)。我们甚至不能使用背景剪辑,因为那样也会剪辑边框。因此,我们必须再次使用线性渐变,其大小比容器的尺寸小四边的填充量。因此,此渐变的背景大小为 calc(100% - 20px) calc(100% - 20px),位置也应相应偏移。
  • 可以通过改变渐变的颜色来改变边框和背景颜色。

div {
  padding: 15px;
  margin-bottom: 10px;
  line-height: 1.4;
  font-size: 14px;
  color: #666;
  background: linear-gradient(#C5C5C5, #C5C5C5), linear-gradient(#C5C5C5, #C5C5C5), linear-gradient(#C5C5C5, #C5C5C5), linear-gradient(#C5C5C5, #C5C5C5), linear-gradient(#ECECEC, #ECECEC);
  background-size: 100% 1px, 1px 100%, 100% 1px, 1px 100%, calc(100% - 20px) calc(100% - 20px);
  background-position: 0px 10px, calc(100% - 10px) 0px, 0px calc(100% - 10px), 10px 0px, 10px 10px;
  background-repeat: no-repeat;
}

/* Just for demo */

h1 {
  margin: 0 0 10px;
  text-transform: uppercase;
  font-weight: 200;
  letter-spacing: 3px;
  font-size: 30px;
  color: #009688;
}
body {
  margin: 0;
  padding: 0;
  width: 100%;
  font-family: Helvetica, Arial, sans-serif;
  /* text-align: center; */
}
<div>
  <h1>Title Text here</h1>
  Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book.</div>

<div>
  <h1>Title Text here</h1>
  Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has
  survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing
  software like Aldus PageMaker including versions of Lorem Ipsum.</div>


如果您需要在每一侧都进行可变扩展,只需根据以下逻辑更改内边距、背景大小和位置即可:

  • 假设您需要边框在顶部扩展 6px,在右侧扩展 8px,在底部扩展 10px,在左侧扩展 12px,并且 space 为 4px在边框和文本之间。然后使用以下逻辑设置填充。

    padding: [border-ext-top + space-between-borders-n-text]
             [border-ext-right + space-between-borders-n-text]
             [border-ext-bottom + space-between-borders-n-text]
             [border-ext-left + space-between-borders-n-text];
    
  • 背景图像渐变(产生边框)设置为遵循与填充相同的从右上角到左下角的顺序。所以,设置 background-position 如下。

    background-position: 0px [border-ext-top], 
                         calc(100% - [border-ext-right]) 0px, 
                         0px calc(100% - [border-ext-bottom]), 
                         [border-ext-left] 0px, 
                         [border-ext-left] [border-ext-top];
    
  • 由于paddingbackground-position改变了,所以创建内部填充的渐变大小也应该改变,以免溢出边界。

    background-size: 100% 1px, 1px 100%, 100% 1px, 1px 100%,
                     calc(100% - [border-ext-left + border-ext-right]) calc(100% - [border-ext-top + border-ext-bottom]);</pre>

div {
  padding: 10px 12px 14px 16px;
  margin-bottom: 10px;
  line-height: 1.4;
  font-size: 14px;
  color: #666;
  background: linear-gradient(#C5C5C5, #C5C5C5), linear-gradient(#C5C5C5, #C5C5C5), linear-gradient(#C5C5C5, #C5C5C5), linear-gradient(#C5C5C5, #C5C5C5), linear-gradient(#ECECEC, #ECECEC);
  background-size: 100% 1px, 1px 100%, 100% 1px, 1px 100%, calc(100% - 20px) calc(100% - 16px);
  background-position: 0px 6px, calc(100% - 8px) 0px, 0px calc(100% - 10px), 12px 0px, 12px 6px;
  background-repeat: no-repeat;
}

/* Just for demo */

h1 {
  margin: 0 0 10px;
  text-transform: uppercase;
  font-weight: 200;
  letter-spacing: 3px;
  font-size: 30px;
  color: #009688;
}
body {
  margin: 0;
  padding: 0;
  width: 100%;
  font-family: Helvetica, Arial, sans-serif;
  /* text-align: center; */
}
<div>
  <h1>Title Text here</h1>
  Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book.</div>

<div>
  <h1>Title Text here</h1>
  Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has
  survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing
  software like Aldus PageMaker including versions of Lorem Ipsum.</div>

另一种解决方案是在 .container 中使用 4 个 span 元素,并使用 before 和 after 伪元素。

我为出站边界使用了几种颜色,你可以理解,css 规则操纵边界。

span 元素绝对定位到父元素。所以这个解决方案是完全响应的。

现在您可以单独操作每条边界线。理论上所有的边界线都可以有不同的高度's/width,这取决于线是水平线还是垂直线。

body {
  margin: 0;
  padding: 0;
  width: 100%;
  font-family: Helvetica, Arial, sans-serif;
}

.container {
  margin: 50px auto 0;
  padding: 0;
  width: 75%;
  position: relative;
}
.container > span:before, .container > span:after {
  content: " ";
  display: block;
  position: absolute;
  background-color: #ccc;
}
.container > span:nth-child(1):before, .container > span:nth-child(1):after {
  width: 10px;
  height: 1px;
  left: 100%;
  background-color: red;
}
.container > span:nth-child(1):before {
  bottom: 0;
}
.container > span:nth-child(1):after {
  top: 0;
}
.container > span:nth-child(2):before, .container > span:nth-child(2):after {
  width: 10px;
  height: 1px;
  right: 100%;
  background-color: blue;
}
.container > span:nth-child(2):before {
  bottom: 0;
}
.container > span:nth-child(2):after {
  top: 0;
}
.container > span:nth-child(3):before, .container > span:nth-child(3):after {
  width: 1px;
  height: 10px;
  bottom: 100%;
  background-color: orange;
}
.container > span:nth-child(3):before {
  right: 0;
}
.container > span:nth-child(3):after {
  left: 0;
}
.container > span:nth-child(4):before, .container > span:nth-child(4):after {
  width: 1px;
  height: 10px;
  top: 100%;
  background-color: green;
}
.container > span:nth-child(4):before {
  right: 0;
}
.container > span:nth-child(4):after {
  left: 0;
}

.box-inner {
  padding: 20px;
  background-color: #ECECEC;
  height: 140px;
  border: 1px solid #ccc;
}

.box-inner h1 {
  margin: 0 0 10px;
  text-transform: uppercase;
  font-weight: 200;
  letter-spacing: 3px;
  font-size: 30px;
  color: #009688;
}

.box-inner p {
  margin: 0;
  line-height: 1.4;
  font-size: 14px;
  color: #666;
}
<div class="container">
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <div class="box-inner">
    <h1>Title Text Here</h1>
    <p>Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Cras mattis consectetur purus sit amet fermentum. Praesent commodo cursus magna, vel scelerisque nisl consectetur et. Vestibulum id ligula porta felis euismod semper.</p>
  </div>
</div>

您可以使用一个元素和几个伪元素来实现这一点。下面是一个快速演示。

div {
  position: relative;
  height: 300px;
  width: 80%;
  margin: 30px;
  background: tomato;
}
div:before {
  content: "";
  position: absolute;
  top: -2px;
  left: -30px;
  width: calc(100% + 60px);
  height: 100%;
  border-top: 2px solid cornflowerblue;
  border-bottom: 2px solid cornflowerblue;
}
div:after {
  content: "";
  position: absolute;
  left: -2px;
  top: -30px;
  height: calc(100% + 60px);
  width: 100%;
  border-left: 2px solid cornflowerblue;
  border-right: 2px solid cornflowerblue;
}
<div>
  <h4>Hello, World!</h4>
  Some Text
</div>

你也可以使用 , background-clip 除了 background-image (gradients), background-size :

https://developer.mozilla.org/en-US/docs/Web/CSS/background-clip

https://developer.mozilla.org/en-US/docs/Web/CSS/background-size

https://developer.mozilla.org/en-US/docs/Web/CSS/linear-gradient

div {
  width:400px;/* whatever*/
  padding:20px;/* you need this ! use same units as for bg-position for better control  */
  margin:2em;/* whatever */
  background:/* draw images needed  to fake borders and bg-color */ 
    linear-gradient(to top, black,black) 1em 0 repeat-y ,
    linear-gradient(to top, black,black) calc( 100% - 1em) 0 repeat-y,
    linear-gradient(to left, black,black) 0 1em repeat-x,
    linear-gradient(to left, black,black) 0 calc(100% - 1em)  repeat-x ,
    linear-gradient(30deg,gray,lightgray) no-repeat;
  
  background-size: 3px 100%, 3px 100%, 100% 3px ,100% 3px , auto auto ;
  background-clip: border-box,border-box,border-box,border-box,content-box;
}
/* add some contet in html to test behavior , you may style it too */
p {
  margin:0;
  padding:0.5em;
  text-align:justify
}
<div>
 <p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo. Quisque sit amet est et sapien ullamcorper pharetra. Vestibulum erat wisi, condimentum sed, commodo vitae, ornare sit met isi.</p>
</div>

实际上与 harry 非常相似,只是不同于用于仅在内容区域内通过渐变绘制背景颜色的背景剪辑属性。

<ul>
<li><img src="#" class="logo"></li>
</u