创建 CSS 双边框线,中间有一个台阶

Creating a CSS double border line with a step in the middle

我正在尝试通过严格 CSS 和 HTML 实现此(下图),以便在移动设备上显示此 header。我能够完成它,尽管我相信我这样做的方式可能是错误的。我将它们添加到两个容器中并让它们正确对齐和连接,这几乎是不可能的。

这是我的 CSS:

#shape1:before{
  position: absolute;
  bottom: 30px; left: -4px;
  content: '';
  height: 15px;
  width: 41%;
  border-bottom: 3.5px solid #000000;
  border-right: 4.5px solid #000000;
  transform: skew(-45deg);
}
#shape1:after{
  position: absolute;
  content: '';
  bottom: 24px; left: 0px;
  height: 16px;
  width: 41%;
  border-bottom: 3.5px solid #000000;
  border-right: 4.5px solid #000000;
  transform: skew(-45deg);
  z-index: -1;
}
#shape1{
  position: relative;
  height: 79.5px;
  width: 400px;
  z-index: -1;
}
#shape:before{
  position: absolute;
  content: '';
  right: 0px;
  width: 57.5%;
  top: 31.2px;
  z-index: -1;
  border-bottom: 3px solid #000000;
  box-shadow: 1px 2px 5px rgba(0,0,0, .3);
}
#shape:after{
  position: absolute;
  content: '';
  top: 36px;
  width: 56.5%;
  z-index: -1;
  right: 0px;
  border-bottom: 3px solid #000000;
  box-shadow: 1px 3px 5px rgba(0,0,0, .3);
}
#shape {
  height: 71px;
  width: 400px;
}

任何link或分享的知识将不胜感激。我现在似乎找不到任何东西。我也不想在其中添加一些阴影,这就是为什么您会在其中找到一些 box-shadow 代码,但还没有 100% 做到这一点。

我在 codepen 上整理了一个响应式示例,两个容器使用 50% 的宽度。这些可以相应地改变。不幸的是,在响应式环境中,除了以像素为单位的精确宽度之外,任何其他内容都会导致线条倾斜部分的宽度发生变化,我相信您已经发现了。

#shape1:before {
  position: absolute;
  bottom: 38.5px;
  left: -10px;
  content: '';
  height: 15px;
  width: 100%;
  border-bottom: 3.5px solid #000000;
  border-right: 4.5px solid #000000;
  transform: skew(-45deg);
  background-color: white;
}
#shape1:after {
  position: absolute;
  content: '';
  bottom: 33px;
  left: -10px;
  height: 16px;
  width: 100%;
  border-bottom: 3.5px solid #000000;
  border-right: 4.5px solid #000000;
  transform: skew(-45deg);
  z-index: -1;
  background-color: white;
}
#shape1 {
  position: relative;
  height: 79.5px;
  width: 50%;
  z-index: -1;
}
#shape:before {
  position: absolute;
  content: '';
  right: 0px;
  width: 50%;
  top: 31.2px;
  z-index: -1;
  border-bottom: 3px solid #000000;
  box-shadow: 1px 2px 5px rgba(0, 0, 0, .3);
}
#shape:after {
  position: absolute;
  content: '';
  top: 36px;
  width: 50%;
  z-index: -1;
  right: 0px;
  border-bottom: 3px solid #000000;
  box-shadow: 1px 3px 5px rgba(0, 0, 0, .3);
}
#shape {
  height: 71px;
  width: 50%;
}
<div id="shape1"></div>
<div id="shape"></div>

我不确定 CSS 是完成此任务的最佳方式。就个人而言,如果我想显示您显示的连接双线,我会使用 SVG。但抛开这些,这里有一个简单的 CSS 解决方案。

此方法使用 CSS 边框、相对定位、转换和 inline-block。它也是响应式的(沿 x 轴)。

让所有三条线路顺利连接并不是一件容易的事(正如你所说)。由于对齐所需的精度,您可能需要调整几个值才能使其在您的站点上工作。不确定这一切是否值得,但如果无法选择图像格式,我希望这会有所帮助。

HTML

<div id="container">
    <div id="left-line"></div>
    <div id="center-line"></div>
    <div id="right-line"></div>
</div>

CSS

#container {
    border-top-style: solid;
    border-top-width: 1px;
    border-top-color: black;
    width: 100%;
    }

#left-line {
    display: inline-block;
    width: 45%;
    height: 100px;
    border-bottom-color: black;
    border-bottom-style: double;
    border-bottom-width: 11px;
    }

#right-line {
    display: inline-block;
    width: 45%;
    height: 100px;
    border-bottom-color: black;
    border-bottom-style: double;
    border-bottom-width: 12px;
    position: relative;
    bottom: 18px;
    left: -15px;
    }

#center-line {
    display: inline-block;
    width: 20px;
    height: 36px;
    border-left-color: black;
    border-left-style: double;
    border-left-width: 11px;
    position: relative;
    left: -2px;
    bottom: -11px;

    -ms-transform: rotate(55deg);
    -webkit-transform: rotate(55deg);
    transform: rotate(55deg);
}

@media screen and (max-width: 500px) {
    #left-line { width: 40%; }
    #right-line { width: 40%; }
}

@media screen and (max-width: 400px) {
    #left-line { width: 35%; }
    #right-line { width: 35%; }
}

@media screen and (max-width: 300px) {
    #center-line { display: none; }
    #right-line { display: none; }
    #left-line { width: 100%; }
}

上面的代码呈现如下:

DEMO:http://jsfiddle.net/o39o17tv/7/(为了效果调整大小window)

顺便说一句,如果你使用实线,对齐问题就没那么严重了:

演示:http://jsfiddle.net/o39o17tv/8/

使用 CSS 变换:

为了使用 CSS 实现双边框而没有任何问题让它们正确对齐,倾斜变换是最好的选择,因为我们总是可以修复变换发生的点(从而消除任何潜在的问题结盟)。然而,我们不能用这种方法使用 double 边界,因为倾斜变换会导致倾斜边上的边界线看起来比顶部和底部的边界线更接近彼此。为了克服这个问题,我们必须使用额外的 child 元素。

输出响应完美,这可以通过在整页中查看代码段输出来验证。

.double-outer-border {
  position: relative;
  border-top: 1px solid;
  height: 100px;
  width: 100%;
  overflow: hidden;
}
.double-outer-border:before,
.double-outer-border:after,
.double-inner-border:before,
.double-inner-border:after {
  position: absolute;
  content: '';
  height: 20px;
  bottom: 0px;
  width: 50%;
  transform: skew(-45deg);
}
.double-outer-border:before {
  left: -2px;
}
.double-outer-border:after {
  right: -2px;
}
.double-inner-border:before {
  left: -4px;
  bottom: 4px;
}
.double-inner-border:after {
  right: 0px;
  bottom: 4px;
}
.double-outer-border:before,
.double-inner-border:before {
  border-bottom: 3px solid;
  border-right: 4px solid;
  transform-origin: right bottom;
}
.double-outer-border:after,
.double-inner-border:after {
  border-top: 3px solid;
  border-left: 4px solid;
  transform-origin: left bottom;
  box-shadow: inset 2px 2px 2px rgba(0, 0, 0, .3);
}
<div class='double-outer-border'>
  Some content
  <div class='double-inner-border'></div>
</div>


使用CSS渐变:

与前面的方法相比,下面是一种非常复杂的方法,但我将其张贴在这里只是为了提供一些不同的想法。整个带有倾斜的双边框可以使用 linear-gradients (以及一些变换)来实现。尽管这会产生预期的输出,我不推荐它。使用这种方法只是为了获得一些关于渐变可以做什么的想法:)

.double-border {
  position: relative;
  height: 100px;
  width: 100%;
  border-top: 1px solid;
  overflow: hidden;
}
.double-border:before {
  position: absolute;
  content: '';
  height: 100%;
  width: calc(50% + 10px);
  left: -10px;
  top: 0px;
  background: linear-gradient(to right, black 99.9%, transparent 99.9%), linear-gradient(to right, black 99.9%, transparent 99.9%);
  background-repeat: no-repeat;
  background-position: -4.5px 97px, -9px 91px;
  background-size: 100% 3px;
}
.double-border:after {
  position: absolute;
  content: '';
  height: 100%;
  width: calc(50% + 10px);
  left: -10px;
  top: 0px;
  background: linear-gradient(to right, black 99.9%, transparent 99.9%), linear-gradient(to right, black 99.9%, transparent 99.9%), linear-gradient(to right, rgba(0,0,0,0.3) 99.9%, transparent 99.9%), linear-gradient(to right, rgba(0,0,0,0.3) 99.9%, transparent 99.9%);
  background-repeat: no-repeat;
  background-position: -7.5px 75px, -9px 81px, -8.5px 77px, -10px 83px;
  background-size: 100% 3px;
  transform: scaleX(-1);
  transform-origin: right;
}
.slanted-border {
  position: absolute;
  height: 25px;
  width: 25px;
  bottom: 3px;
  left: 50%;
  transform: translateX(-50%) rotate(-45deg);
  background: linear-gradient(to right, black 99%, transparent 99%), linear-gradient(to right, black 95%, transparent 95%), linear-gradient(to right, rgba(0,0,0,0.3) 99%, transparent 99%), linear-gradient(to right, rgba(0,0,0,0.3) 95%, transparent 95%);
  background-repeat: no-repeat;
  background-position: 0px 11px, -2px 17px, 0px 13px, -2px 19px;
  background-size: 100% 3px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>
<div class='double-border'>
  Some Content
  <div class='slanted-border'></div>
</div>


使用 SVG:

一般来说,绘制此类形状或复杂线条的最简单方法是 SVG(它还具有响应迅速的优点,可以适应尺寸的任何变化),但使用 SVG 有一些缺点:

  • 如果 header 的高度不变,只有宽度根据设备发生变化,则 SVG 将必须 stretch/shrink 以适应容器(取决于原始尺寸),这会使中间的斜线看起来嘎吱作响(或)拉长。 (以整页模式查看代码段。)
  • 在 SVG 中,描边也会默认缩放。这可以通过将 vector-effect 属性设置为 non-scaling-stroke 来避免,但目前 IE 不支持此 属性,因此此解决方案与 cross-browser 不兼容。

path {
  stroke: black;
  fill: none;
  stroke-width: 2;
}
svg {
  height: 100px;
  width: 100%;
  border-top: 1px solid;
}
<svg viewBox='0 0 500 100' preserveaspectratio='none'>
  <path d='M0,98 240,98 260,75 500,75' vector-effect='non-scaling-stroke'/>
  <path d='M0,94 237.5,94 257.5,71 500,71' vector-effect='non-scaling-stroke'/>
</svg>

双斜边框

注意 建议为此使用 SVG。

CSS:

  • 一个元素
  • 两个伪元素

使用了很多 calc() 和百分比值来让它完全响应。
使用了很多边框样式 double 因为这似乎是渲染边框的最简单方法。
一个倾斜的元素是一个具有白色背景的绝对定位元素。
所以你可能需要有纯色背景。

.extra-border {
  position: relative;
  border-bottom: 11px double black;
  border-top: 3px solid black;
  height: 150px;
  width: 100%;
  box-sizing: border-box;
}
.extra-border::before {
  content: "";
  position: absolute;
  display: inline-block;
  width: 50%;
  height: 15%;
  background-color: white;
  bottom: -11px;
  right: 0;
  border-top: 11px double black;
  border-bottom: 11px solid transparent;
}
.extra-border::after {
  content: "";
  position: absolute;
  display: inline-block;
  background-color: white;
  width: 20px;
  height: calc(20% + 19px);
  border-left: 13px double black;
  right: calc(50% - 11px);
  bottom: -20px;
  transform-origin: center center;
  transform: rotate(45deg);
}
<div class="extra-border"></div>