CSS: 响应式文本和渐变背景/边框的长六边形

6

我正在尝试创建两个类似的长六边形,如下图所示:

enter image description here

主要特点应该包括:

  • 可以添加渐变背景
  • 可以添加渐变边框
  • 文本可以是单行或双行
  • 响应式布局(Bootstrap网格)(最好有) - 角落的角度应始终相同。

根据仅使用一个元素创建长六边形形状按钮,到目前为止,最好的解决方案如下:https://jsfiddle.net/veuc78af/

/*hexagons*/
 .hexagon {
    box-sizing: border-box;
    position: relative;
    display: inline-block;
    min-width: 200px;
    height: 80px;
    margin: 40px auto;
    color: #fd0;
    text-align: center;
    text-decoration: none;
    line-height: 80px;
}
.hexagon:before, .hexagon:after {
    position: absolute;
    content:'';
    width: 100%;
    left: 0px;
    height: 34px;
    z-index: -1;
}
.hexagon:before {
    transform: perspective(15px) rotateX(3deg);
}
.hexagon:after {
    top: 40px;
    transform: perspective(15px) rotateX(-3deg);
}
/* hexagon Border Style */
 .hexagon.border:before, .hexagon.border:after {
    border: 4px solid #fd0;
}
.hexagon.border:before {
    border-bottom: none;
    /* to prevent the border-line showing up in the middle of the shape */
}
.hexagon.border:after {
    border-top: none;
    /* to prevent the border-line showing up in the middle of the shape */
}
/* hexagon hover styles */
 .hexagon.border:hover:before, .hexagon.border:hover:after {
    background: #fd0;
}
.hexagon.border:hover {
    color: #fff;
}

这个解决方案的主要问题是无法创建渐变背景。所以在我的情况下这行不通。
有没有可能做到呢?
这个项目的主要平台是iPad2上的Safari。

1
你的最佳解决方案是使用SVG。我们可以研究CSS clip-path,但浏览器支持很差(IE根本不支持它,FF需要SVG作为路径提供)。 - Harry
你可以使用JS/JQuery来实现这个功能,通过计算/设置字符串中字符的数量,来计算/设置六边形的宽度。其他特性可以在CSS3中实现。但是这种解决方案将意味着你需要为每个六边形设置一个唯一的ID来设置宽度... - Aeldred
我认为SVG也是最好的解决方案。我忘了说我的项目的主要设备是苹果iPad。我会更新这个并添加标签“svg”。 - Crack_David
2个回答

7

使用CSS Clip Path:

这个项目的主要平台是iPad2上的Safari浏览器。

由于您的主要平台是Safari,并且它支持使用形状的CSS clip-path, 您可以利用该功能来创建类似下面演示的延长六边形的形状。

此方法生成的输出将支持(a)渐变背景(b)模拟通过放置具有非常相似clip-path但尺寸较小的伪元素的渐变边框(c)两行文本(d)还保持角度的角,因为点之间的距离是固定的像素。

.hex {
  position: relative;
  float: left;
  height: 100px;
  min-width: 100px;
  padding: 12px;
  margin: 4px;
  font-weight: bold;
  text-align: center;
  background: linear-gradient(to right, rgb(199, 41, 41), rgb(243, 67, 54));
  -webkit-clip-path: polygon(25px 0px, calc(100% - 25px) 0px, 100% 50%, calc(100% - 25px) 100%, 25px 100%, 0px 50%);
}
.hex.gradient-bg {
  color: white;
}
.hex.gradient-border {
  color: rgb(199, 41, 41);
}
.hex:before {
  position: absolute;
  content: '';
  height: calc(100% - 14px);  /* 100% - 2 * border width */
  width: calc(100% - 14px);  /* 100% - 2 * border width */
  left: 7px; /* border width */
  top: 7px; /* border width */
  -webkit-clip-path: polygon(22px 0px, calc(100% - 22px) 0px, 100% 50%, calc(100% - 22px) 100%, 22px 100%, 0px 50%);
  z-index: -1;
}
.hex.gradient-bg:before {
  background: linear-gradient(to right, rgb(199, 41, 41), rgb(243, 67, 54));
}
.hex.gradient-border:before {
  background: rgb(245, 246, 248);
}
span {
  display: block;
  margin-top: 50px;
  padding: 8px;
  transform: translateY(-50%);
}
<div class='hex gradient-border'>
  <span>Some text</span>
</div>
<div class='hex gradient-bg'>
  <span>Some very lengthy text</span>
</div>
<div class='hex gradient-bg'>
  <span>Some very lengthy text
  <br/>with line break</span>
</div>
<div class='hex gradient-bg'>
  <span>Some very lengthy text
  without line break</span>
</div>


使用SVG:

同样可以使用SVG来实现,就像下面的演示一样。只需要创建一个六边形形状的path,然后将该path图像放置在容器后面。

唯一的缺点是,与CSS clip-path不同,没有非JS方法使角度保持不变。

.hex {
  position: relative;
  height: 100px;
  min-width: 100px;
  padding: 12px 24px;
  margin: 4px;
  float: left;
  font-weight: bold;
  text-align: center;
}
.hex.gradient-bg {
  color: white;
}
.hex.gradient-border {
  color: rgb(199, 41, 41);
}
.hex svg {
  position: absolute;
  height: 100%;
  width: 100%;
  top: 0px;
  left: 0px;
  z-index: -1;
}
path {
  stroke: url(#brdgrad);
  stroke-width: 7; /* border width */
}
.hex.gradient-bg path {
  fill: url(#bggrad);
}
.hex.gradient-border path {
  fill: rgb(245, 246, 248);
}
span {
  display: block;
  margin-top: 50px;
  padding: 8px;
  transform: translateY(-50%);
}
<svg width='0' height='0'>
  <defs>
    <linearGradient id='bggrad'>
      <stop offset='0%' stop-color='rgb(199, 41, 41)' />
      <stop offset='100%' stop-color='rgb(243, 67, 54)' />
    </linearGradient>
    <linearGradient id='brdgrad'>
      <stop offset='0%' stop-color='rgb(199, 41, 41)' />
      <stop offset='100%' stop-color='rgb(243, 67, 54)' />
    </linearGradient>
  </defs>
</svg>
<div class='hex gradient-border'>
  <svg viewBox='0 0 100 100' preserveAspectRatio='none'>
    <path d='M25,7 L75,7 93,50 75,93 25,93 7,50z' vector-effect='non-scaling-stroke' />
  </svg>
  <span>Some text</span>
</div>

<div class='hex gradient-bg'>
  <svg viewBox='0 0 100 100' preserveAspectRatio='none'>
    <path d='M25,7 L75,7 93,50 75,93 25,93 7,50z' vector-effect='non-scaling-stroke' />
  </svg>
  <span>Some very lengthy text</span>
</div>

<div class='hex gradient-bg'>
  <svg viewBox='0 0 100 100' preserveAspectRatio='none'>
    <path d='M25,7 L75,7 93,50 75,93 25,93 7,50z' vector-effect='non-scaling-stroke' />
  </svg>
  <span>Some very lengthy text
  <br>with line break.</span>
</div>

<div class='hex gradient-bg'>
  <svg viewBox='0 0 100 100' preserveAspectRatio='none'>
    <path d='M25,7 L75,7 93,50 75,93 25,93 7,50z' vector-effect='non-scaling-stroke' />
  </svg>
  <span>Some lengthy text
  without line break.</span>
</div>

(不要被SVG代码的长度吓到,它之所以这么大只是因为我重复了多次 - 每个容器都需要一次。但这可以减少。)


哇,版本1太完美了!由于我不熟悉SVG和clip-path:我该如何修改边框宽度?在我的示例中应为7像素。 - Crack_David
@Crack_David:这应该很简单。伪元素的“top”和“left”应该等于“border-width”,而它们的“height”和“width”应该比“border-width”小2倍,这使得伪元素可以很好地嵌套在容器内部,从而使容器的背景看起来像边框。 - Harry
(注意:根据 border-width 的不同,您可能需要对伪元素的 clip-path 进行一次编辑。如果您在演示中看到,父元素左右的剪辑为15px,但在子元素上为13px,以保持整个厚度相同。这将不幸地成为试错过程,据我所知没有其他方法。) - Harry
1
啊,现在我明白了。非常感谢! - Crack_David

0
.hexagon {
  position: relative;
  width: 180px; 
  height: 103.92px;
  background-color: #ffffff;
  margin: 51.96px 0;
  border-left: solid 5px #808080;
  border-right: solid 5px #808080;
}

.hexagon:before,
.hexagon:after {
  content: "";
  position: absolute;
  z-index: 1;
  width: 127.28px;
  height: 127.28px;
  -webkit-transform: scaleY(0.5774) rotate(-45deg);
  -ms-transform: scaleY(0.5774) rotate(-45deg);
  transform: scaleY(0.5774) rotate(-45deg);
  background-color: inherit;
  left: 21.3604px;
}

.hexagon:before {
  top: -63.6396px;
  border-top: solid 7.0711px #808080;
  border-right: solid 7.0711px #808080;
}

.hexagon:after {
  bottom: -63.6396px;
  border-bottom: solid 7.0711px #808080;
  border-left: solid 7.0711px #808080;
}

.hexText{
     position: absolute;
    top: 59px;
    z-index: 999;
    left: 12%;
    text-align:center;
}


.bgGrey{
    background:#e7e6e6 !important; 
}




 <div class="row">
                <div class="col-md-3 col-xs-12">
                    <div class="hexagon"></div>
                    <p class="hexText">Up to 20% increase<br />in sales with<br />Cross sell & Up sell</p>
                </div>
                <div class="col-md-3 col-xs-12">
                    <div class="hexagon bgGrey"></div>
                    <p class="hexText">Up to 35%reduction<br />in print ,postage ,<br />logistic & back<br />office cost</p>
                </div>
                <div class="col-md-3 col-xs-12">
                    <div class="hexagon"></div>
                    <p class="hexText">Scalable100+million <br />statements<br />processed & <br />distributed monthly </p>
                </div>
                <div class="col-md-3 col-xs-12">
                    <div class="hexagon bgGrey"></div>
                    <p class="hexText">Up to 35%reduction<br />in print ,postage ,<br />logistic & back<br />office cost</p>
                </div>
            </div>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接