关于前端:不规则图形背景排版高阶技巧-酷炫的六边形网格背景图

10次阅读

共计 6042 个字符,预计需要花费 16 分钟才能阅读完成。

明天,收到一个很有意思的发问,如何实现相似如下的背景效果图:

嗯?外围主体是由多个六边形网格叠加造成。

那么咱们该如何实现它呢?应用纯 CSS 可能实现吗?

当然能够,上面咱们就将尝试如何应用 CSS 去实现这样一个背景成果。

如何绘制六边形?

首先,看到这样一个图形,如果想要应用一个标签实现整个背景,最先想到的必定是应用背景 background 实现,不过惋惜的是,只管 CSS 中的 background 十分之弱小,然而没有特地好的形式让它足以批量生成反复的六边形背景。

因而,在这个需要中,咱们可能不得不退而求其次,一个六边形实现应用一个标签实现。

那么,就拿 1 个 DIV 来说,咱们有多少实现六边形的形式呢?这里简略介绍 2 种形式:

  • 应用 border 实现六边形
  • 应用 clip-path 实现六边形

应用 border 或者 clip-path 实现六边形

首先,应用 border 实现六边形。这里的外围在于高低两个三角形叠加两头一个矩形。这里,利用元素的两个伪元素实现高低两个三角形,从而让这个元素看起来像一个六边形。

思路比较简单,间接上代码:

.hexagon {
  position: relative;
  width: 200px;
  height: 100px;
  background-color: red;
}

.hexagon:before,
.hexagon:after {
  content: "";
  position: absolute;
  width: 0;
  height: 0;
  border-left: 100px solid transparent;
  border-right: 100px solid transparent;
}

.hexagon:before {
  bottom: 100%;
  border-bottom: 50px solid red;
}

.hexagon:after {
  top: 100%;
  border-top: 50px solid red;
}

下面的代码会创立一个宽度为 200 像素,高度为 100 像素的六边形,其中由两个三角形和一个矩形组成。应用伪元素的长处是能够很不便地管制六边形的大小、色彩等款式。

当然,上述的代码不是一个正六边形,这是因为正六边形中, 元素的高是元素的宽的 1.1547 倍

并且,上述的形式也略微简单了点,因而,在明天,咱们更举荐应用 clip-path 的形式去实现一个六边形:

.clippath {
    --w: 100px;
    width: var(--w);
    height: calc(var(--w) * 1.1547);
    clip-path: polygon(0% 25%, 0% 75%, 50% 100%, 100% 75%, 100% 25%, 50% 0%);
    background: deeppink;
    margin: auto;
}

这样,基于 clip-path,也能疾速失去一个六边形图形:

CodePen Demo — Two ways to achieve a hexagon

绘制多个六边形背景

好了,有了上一步的铺垫之后,接下来咱们要做的,就是绘制多个六边形,组成背景。

然而咱们仔细观察一下由多个六边形组成的背景,会发现每单数行的的六边形,须要向右侧有一个显著的缩进,宽度大略为单个六边形的宽度的一半:

这里其实是一个十分辣手的问题。首先,咱们会想到这样一种解决方案:

  1. 每一行为一组,设置一个父 div 容器,填满六边形元素,设置元素不换行
  2. 给偶数行设置一个固定的 margin-left

基于这个策略,咱们的代码,大略会是这样:

<div class="container">
    <div class="wrap">
    // ... 填满六边形
    </div>
    <div class="wrap" style="margin-left: 25px">
    // ... 填满六边形
    </div>
    <div class="wrap">
    // ... 填满六边形
    </div>
    <div class="wrap" style="margin-left: 25px">
    // ... 填满六边形
    </div>
</div>

能够看到,咱们给偶数行,都增加了一个 margin-left

然而这个代码,会有几个问题:

  1. 咱们的页面宽度不肯定是固定的,那么每一行设置多少个子六边形元素比拟适合呢?设置多了势必会带来节约,少了又无奈满足需要
  2. 多了一层嵌套,代码逻辑更为简单

什么意思呢?也就是成果可能在屏幕十分宽的状况下,生效。

看看,失常状况,咱们设置了每行 20 个六边形,下图是失常的

然而如果咱们的屏幕特地宽,那么,可能会失去这样一种成果:

因而,这种形式存在十分大的弊病,咱们心愿能有一整布局形式,可能满足咱们如下两个诉求:

  1. 所有六边形代码写在一个父容器下
  2. 这个弹性布局中,第二行的元素最右边,可能实现固定一个缩进

认真思考一下,CSS 中有可能实现相似布局的办法么?

妙用 shape-outside 实现隔行错位布局

有的!在 CSS 中,有一个神奇的元素可能让元素以非直线模式排布。它就是 shape-outside

如果你对 shape-outside 不太理解,也能够先看看我的这篇文章 — 微妙的 CSS shapes

shape-outside 是 CSS 中的一个属性,用于管制元素的浮动形式。它容许你定义一个元素浮动时四周元素的形态。例如,你能够应用 shape-outside 属性来定义一个元素浮动时四周元素的形态为圆形、六边形等。

它和 clip-path 的语法十分相似,很容易举一反三。看看实例,更易了解:

假如咱们有上面这样的构造存在:

<div class="container">
    <div class="shape-outside">
      <img src="image.png">
    </div>
    xxxxxxxxxxx,文字描述,xxxxxxxxx
</div>

定义如下 CSS:

.shape-outside {
    width: 160px;
    height: 160px;
    shape-outside: circle(80px at 80px 80px);
    float: left;
}

留神,下面 .shape-outside 应用了浮动,并且定义了 shape-outside: circle(80px at 80px 80px),示意在元素的 (80px, 80px) 坐标处,生成一个 80px 半径的圆。

如此,将会产生一种图文混排的成果:

CodePen Demo — 图文混排 shape-outside

总得来说,shape-outside 有两个外围特点:

  1. shape-outside 属性仅在元素定义了 float 属性且不为 none 时才会失效
  2. 它可能实现了文字依据图形的轮廓,在其四周排列

shape-outside 的实质

划重点,划重点,划重点。

所以,shape-outside 的实质其实是生成几何图形, 并且裁剪掉其几何图形之外四周的区域,让内容能排列在这些被裁剪区域之内

所以,理解了这个实质之后,咱们再将他使用在下面的六边形布局之中。

为了不便了解,咱们首先应用文字代替下面的六边形,假如咱们有这样一段文本内容:

<p>
Lorem ipsum dolor sit amet conse...
</p>
p {
    line-height: 36px;
    font-size: 24px;
}

十分平平无奇的一段代码,成果如下:

当初,咱们想利用 shape-outside,让文本内容的偶数行,向内缩进 24px,怎么实现呢?非常简单:

p {
    position: relative;
    line-height: 36px;
    font-size: 24px;

    &::before {
        content: "";
        height: 100%;
        width: 24px;
        shape-outside: repeating-linear-gradient(
            transparent 0,
            transparent 36px,
            #000 36px,
            #000 72px
        );
        float: left;
    }
}

这样,咱们就实现了文字隔行缩进 24px 的成果:

肯定有小伙伴会很好奇,为什么呢?外围在于咱们利用元素的伪元素实现了一个 shape-outside 图形,如果咱们把这个图形用 background 绘制进去,其实它长这样:


p {
    position: relative;
    line-height: 36px;
    font-size: 24px;

    &::before {
        content: "";
        height: 100%;
        width: 24px;
        shape-outside: repeating-linear-gradient(
            transparent 0,
            transparent 36px,
            #000 36px,
            #000 72px
        );
        float: left;
        background: repeating-linear-gradient(
            transparent 0,
            transparent 36px,
            #f00 36px,
            #f00 72px
        );
    }
}

成果如下:

因为文本的行高是 36px,这样咱们以 72 为一段,每 36px 绘制一段通明,另外 36px 绘制一段宽为 24px 的内容,这样,联合 shape-outside 的个性,咱们就实现了隔即将内容向外面挤 24px 的成果!

十分的 Amazing 的技巧!残缺的代码你能够戳这里:

CodePen Demo — Shape-outside achieves even line indentation

基于这个技巧,咱们就能够实现上述咱们想要的成果了。咱们回到正题,从新实现一个充斥六边形的背景:

<ul class="wrap">
  <li></li>
  //... 十分多个 li
<ul>
:root {
  --s: 50px;  /* size  */
  --m: 4px;    /* margin */
  --perHeight: calc(calc(var(--s) * 2 * 1.1547) + calc(var(--m) * 4) - 0.4px)
}

.wrap {
    position: relative;
    height: 100%;
    font-size: 0;

    &::before {
        content: "";
        height: 100%;
        width: 27px;
        shape-outside: repeating-linear-gradient(
            transparent 0,
            transparent 70px,
            #000 70px,
            #000 var(--perHeight)
        );
        float: left;
    }
}

li {width: var(--s);
    height: calc(var(--s) * 1.1547); 
    background: #000;
    clip-path: polygon(0% 25%, 0% 75%, 50% 100%, 100% 75%, 100% 25%, 50% 0%);
    margin: var(--m);
    display: inline-block;
}

借助 shape-outside,咱们就实现了隔行让咱们的六边形向内缩进的诉求!成果如下:

当然,有一些优化点:

  1. 为了让两边不那么空,咱们能够让整个容器更宽一点,譬如宽度为父元素的 120%,而后程度居中,这样,两侧的留白就解决了
  2. 让两行间接贴紧,能够设置一个 margin-bottom

做完这两点优化之后,成果如下:

能够做到任意屏幕宽度下的六边形完满平铺布局:

残缺的代码你能够戳这里:CodePen Demo — Hexagon Layout

配置上色调变换

有了上述的铺垫后,要实现文章一结尾的成果就不难了。

是的,咱们要实现这样一个成果:

如何让它们动静的实现色彩变换呢?是给每一个六边形一个独自的色彩,而后进行动画吗?不,借助混合模式,咱们能够十分疾速的实现不同的色彩值。

首先,咱们将上述成果,改成白底彩色六边形色块:

而后,利用父容器残余的一个伪元素,咱们叠加一层突变层下来:

.wrap {
    position: relative;
    // 代码与上述保持一致

    &::before {
        content: "";
        // ... 实现 shape-outside 性能,代码与上述保持一致
    }
    
    &::after {
        content: "";
        position: absolute;
        inset: 0;
        background: linear-gradient(45deg, #f44336, #ff9800, #ffe607, #09d7c4, #1cbed3, #1d8ae2, #bc24d6);
    }
}

这样,咱们就叠加了一层突变色调层在本来的六边形背景之上:

接着,只须要一个混合模式 mix-blend-mode: darken,就能实现六边形色块与下层突变色彩的交融成果:

.wrap {
    position: relative;
    // 代码与上述保持一致

    &::before {
        content: "";
        // ... 实现 shape-outside 性能,代码与上述保持一致
    }
    
    &::after {
        content: "";
        position: absolute;
        inset: 0;
        background: linear-gradient(45deg, #f44336, #ff9800, #ffe607, #09d7c4, #1cbed3, #1d8ae2, #bc24d6);
        z-index: 1;
      + mix-blend-mode: darken;
    }
}

成果如下:

好,咱们再给下层的渐变色块,增加一个 filter: hue-rotate() 动画,实现色调的突变动画:

.wrap {
    position: relative;
    // 代码与上述保持一致

    &::before {
        content: "";
        // ... 实现 shape-outside 性能,代码与上述保持一致
    }
    
    &::after {
        content: "";
        position: absolute;
        inset: 0;
        background: linear-gradient(45deg, #f44336, #ff9800, #ffe607, #09d7c4, #1cbed3, #1d8ae2, #bc24d6);
        z-index: 1;
        mix-blend-mode: darken;
      + animation: change 10s infinite linear;
    }
}
@keyframes change {
    100% {filter: hue-rotate(360deg);
    }
}

这样,咱们就完满的实现了咱们想要的成果:

残缺的代码,你能够戳这里:CodePen Demo — Hexagon Gradient Layout

扩大延长

当然,有了这个根底图形之后,其实咱们能够基于这个图形,去做十分多有意思的成果。

上面我是尝试的一些成果示意,譬如,咱们能够将色彩搁置在六边形背景的下方,制作这样一种成果:

CodePen Demo — Hexagon Gradient Layout

配合 mask 的蒙版成果及鼠标定位,咱们还能实现这样一种乏味的交互成果:

CodePen Demo — Hexagon Gradient & MASK Layout

当然,3D 成果也不在话下:

CodePen Demo — 3D Hexagon Gradient Layout

最初

好了,本文到此结束,心愿本文对你有所帮忙 :)

更多精彩 CSS 技术文章汇总在我的 Github — iCSS,继续更新,欢送点个 star 订阅珍藏。

如果还有什么疑难或者倡议,能够多多交换,原创文章,文笔无限,满腹经纶,文中若有不正之处,万望告知。

正文完
 0