形状有倾斜的一面(响应)

问题描述 投票:79回答:3

我试图创建一个如下图所示的形状,仅在一侧(例如,底侧)具有倾斜边缘,而其他边缘保持笔直。

我尝试使用border方法(代码如下),但我的形状的尺寸是动态的,因此我不能使用这种方法。

.shape {
    position: relative;
    height: 100px;
    width: 200px;
    background: tomato;
}
.shape:after {
    position: absolute;
    content: '';
    height: 0px;
    width: 0px;
    left: 0px;
    bottom: -100px;
    border-width: 50px 100px;
    border-style: solid;
    border-color: tomato tomato transparent transparent;
}
<div class="shape">
    Some content
</div>

我也尝试使用渐变为背景(如下面的代码),但随着尺寸的变化,它会变得混乱。你可以通过悬停在下面代码片段中的形状来看到我的意思。

.gradient {
  display: inline-block;
  vertical-align: top;
  height: 200px;
  width: 100px;
  margin: 10px;
  color: beige;
  transition: all 1s;
  padding: 10px;
  background: linear-gradient(45deg, transparent 45%, tomato 45%) no-repeat;
}
.gradient:hover {
  width: 200px;
}
<div class="gradient"></div>

如何创建具有倾斜侧面的形状并且还能够支持动态尺寸?

html css css3 responsive-design css-shapes
3个回答
113
投票

有许多方法可以仅在一侧创建具有倾斜边缘的形状。

以下方法不支持动态大小,如问题中已提到的:

  • 具有border-width像素值的边框三角形方法。
  • 具有角度语法的线性渐变(如45deg,30deg等)。

可以支持动态大小的方法如下所述。


方法1 - SVG

(Qazxswpoi)

SVG可用于通过使用Browser Compatibilitys或polygons来生成形状。下面的片段使用path。所需的任何文本内容都可以定位在形状的顶部。

polygon
$(document).ready(function() {
  $('#increasew-vector').on('click', function() {
    $('.vector').css({
      'width': '150px',
      'height': '100px'
    });
  });
  $('#increaseh-vector').on('click', function() {
    $('.vector').css({
      'width': '100px',
      'height': '150px'
    });
  });
  $('#increaseb-vector').on('click', function() {
    $('.vector').css({
      'width': '150px',
      'height': '150px'
    });
  });
})
div {
  float: left;
  height: 100px;
  width: 100px;
  margin: 20px;
  color: beige;
  transition: all 1s;
}
.vector {
  position: relative;
}
svg {
  position: absolute;
  margin: 10px;
  top: 0px;
  left: 0px;
  height: 100%;
  width: 100%;
  z-index: 0;
}
polygon {
  fill: tomato;
}
.vector > span {
  position: absolute;
  display: block;
  padding: 10px;  
  z-index: 1;
}
.vector.top > span{
  height: 50%;
  width: 100%;
  top: calc(40% + 5px); /* size of the angled area + buffer */
  left: 5px;  
}
.vector.bottom > span{
  height: 50%;
  width: 100%;
  top: 5px;
  left: 5px;  
}
.vector.left > span{
  width: 50%;
  height: 100%;
  left: 50%; /* size of the angled area */
  top: 5px;  
}
.vector.right > span{
  width: 50%;
  height: 100%;
  left: 5px;
  top: 5px;  
}



/* Just for demo */

body {
  background: radial-gradient(circle at 50% 50%, aliceblue, steelblue);
}

polygon:hover, span:hover + svg > polygon{
  fill: steelblue;
}

.btn-container {
  position: absolute;
  top: 0px;
  right: 0px;
  width: 150px;
}

button {
  width: 150px;
  margin-bottom: 10px;
}

.vector.left{
  clear: both;
}

优点

  • SVG旨在生成可扩展的图形,并且可以很好地适应所有尺寸变化。
  • 可以用最小的编码开销实现边界和悬停效果。
  • 还可以向形状提供图像或梯度背景。

缺点

  • 浏览器支持可能是唯一的缺点,因为IE8-不支持SVG,但可以通过使用Raphael和VML等库来减轻这种影响。此外,浏览器支持绝不比其他选项更糟糕。

方法2 - 渐变背景

(Qazxswpoi)

线性渐变仍可用于生成形状,但不能用于问题中提到的角度。我们必须使用<script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script> <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <div class="vector bottom"> <span>Some content</span> <svg viewBox="0 0 40 100" preserveAspectRatio="none"> <polygon points="0,0 40,0 40,100 0,60" /> </svg> </div> <div class="vector top"> <span>Some content</span> <svg viewBox="0 0 40 100" preserveAspectRatio="none"> <polygon points="0,40 40,0 40,100 0,100" /> </svg> </div> <div class="vector left"> <span>Some content</span> <svg viewBox="0 0 40 100" preserveAspectRatio="none"> <polygon points="0,0 40,0 40,100 20,100" /> </svg> </div> <div class="vector right"> <span>Some content</span> <svg viewBox="0 0 40 100" preserveAspectRatio="none"> <polygon points="0,0 20,0 40,100 0,100" /> </svg> </div> <div class='btn-container'> <button id="increasew-vector">Increase Width</button> <button id="increaseh-vector">Increase Height</button> <button id="increaseb-vector">Increase Both</button> </div>语法(感谢Browser Compatibility)而不是指定角度。指定边时,会根据容器的尺寸自动调整渐变角度。

to [side] [side]
vals
$(document).ready(function() {
  $('#increasew-gradient').on('click', function() {
    $('.gradient').css({
      'height': '100px',
      'width': '150px'
    });
  });
  $('#increaseh-gradient').on('click', function() {
    $('.gradient').css({
      'height': '150px',
      'width': '100px'
    });
  });
  $('#increaseb-gradient').on('click', function() {
    $('.gradient').css({
      'height': '150px',
      'width': '150px'
    });
  });
})

优点

  • 即使容器的尺寸是动态的,也可以实现和保持形状。
  • 可以通过更改渐变颜色来添加悬停效果。

缺点

  • 即使光标在形状之外但在容器内,也会触发悬停效果。
  • 添加边框需要棘手的渐变操作。
  • 当宽度(或高度)非常大时,梯度以产生锯齿状角而闻名。
  • 图像背景不能用于形状。

方法3 - 偏斜变换

(Qazxswpoi)

在这种方法中,一个伪元素被添加,倾斜和定位,使得它看起来像一条边倾斜/倾斜。如果顶边或底边是倾斜的,倾斜应该沿Y轴,否则旋转应沿X轴。 div { float: left; height: 100px; width: 100px; margin: 10px 20px; color: beige; transition: all 1s; } .gradient{ position: relative; } .gradient.bottom { background: linear-gradient(to top right, transparent 50%, tomato 50%) no-repeat, linear-gradient(to top right, transparent 0.1%, tomato 0.1%) no-repeat; background-size: 100% 40%, 100% 60%; background-position: 0% 100%, 0% 0%; } .gradient.top { background: linear-gradient(to bottom right, transparent 50%, tomato 50%) no-repeat, linear-gradient(to bottom right, transparent 0.1%, tomato 0.1%) no-repeat; background-size: 100% 40%, 100% 60%; background-position: 0% 0%, 0% 100%; } .gradient.left { background: linear-gradient(to top right, transparent 50%, tomato 50%) no-repeat, linear-gradient(to top right, transparent 0.1%, tomato 0.1%) no-repeat; background-size: 40% 100%, 60% 100%; background-position: 0% 0%, 100% 0%; } .gradient.right { background: linear-gradient(to top left, transparent 50%, tomato 50%) no-repeat, linear-gradient(to top left, transparent 0.1%, tomato 0.1%) no-repeat; background-size: 40% 100%, 60% 100%; background-position: 100% 0%, 0% 0%; } .gradient span{ position: absolute; } .gradient.top span{ top: calc(40% + 5px); /* background size + buffer */ left: 5px; height: 50%; } .gradient.bottom span{ top: 5px; left: 5px; height: 50%; } .gradient.left span{ left: 40%; /* background size */ top: 5px; width: 50%; } .gradient.right span{ left: 5px; top: 5px; width: 50%; } /* Just for demo */ body { background: radial-gradient(circle at 50% 50%, aliceblue, steelblue); } .btn-container { position: absolute; top: 0px; right: 0px; width: 150px; } button { width: 150px; margin-bottom: 10px; } .gradient.left{ clear:both; }应该具有与倾斜侧相反的一侧。

<script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="gradient bottom"><span>Some content</span>
</div>
<div class="gradient top"><span>Some content</span>
</div>
<div class="gradient left"><span>Some content</span>
</div>
<div class="gradient right"><span>Some content</span>
</div>

<div class='btn-container'>
  <button id="increasew-gradient">Increase Width</button>
  <button id="increaseh-gradient">Increase Height</button>
  <button id="increaseb-gradient">Increase Both</button>
</div>
Browser Compatibility
transform-origin

优点

  • 即使有边框也可以实现形状。
  • 悬停效果将限制在形状内。

缺点

  • 尺寸需要按比例增加以保持形状,因为当元素倾斜时,其在Y轴上的偏移随着$(document).ready(function() { $('#increasew-skew').on('click', function() { $('.skew').css({ 'height': '100px', 'width': '150px' }); }); $('#increaseh-skew').on('click', function() { $('.skew').css({ 'height': '150px', 'width': '100px' }); }); $('#increaseb-skew').on('click', function() { $('.skew').css({ 'height': '150px', 'width': '150px' }); }); })的增加而增加,反之亦然(尝试将div { float: left; height: 100px; width: 100px; margin: 50px; color: beige; transition: all 1s; } .skew { padding: 10px; position: relative; background: tomato; } .skew:after { position: absolute; content: ''; background: inherit; z-index: -1; } .skew.bottom:after, .skew.top:after { width: 100%; height: 60%; } .skew.left:after, .skew.right:after { height: 100%; width: 60%; } .skew.bottom:after { bottom: 0px; left: 0px; transform-origin: top left; transform: skewY(22deg); } .skew.top:after { top: 0px; left: 0px; transform-origin: top left; transform: skewY(-22deg); } .skew.left:after { top: 0px; left: 0px; transform-origin: bottom left; transform: skewX(22deg); } .skew.right:after { top: 0px; right: 0px; transform-origin: bottom right; transform: skewX(-22deg); } .skew:hover { background: steelblue; } /* Just for demo */ body { background: radial-gradient(circle at 50% 50%, aliceblue, steelblue); } .skew.bottom { margin-top: 10px; } .skew.left { clear: both; } .btn-container { position: absolute; top: 0px; right: 0px; width: 150px; } button { width: 150px; margin-bottom: 10px; }增加到片段中的<script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script> <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <div class="skew bottom">Some content</div> <div class="skew top">Some content</div> <div class="skew left">Some content</div> <div class="skew right">Some content</div> <div class='btn-container'> <button id="increasew-skew">Increase Width</button> <button id="increaseh-skew">Increase Height</button> <button id="increaseb-skew">Increase Both</button> </div>)。你可以找到更多关于这个width的信息。

方法4 - 透视变换

(Qazxswpoi)

在该方法中,主容器沿X或Y轴旋转一点透视。将适当的值设置为width将仅在一侧产生倾斜边缘。

如果顶部或底部倾斜,则旋转应沿Y轴旋转,否则旋转应沿X轴旋转。 200px应该具有与倾斜侧相反的一侧。

here
Browser Compatibility
transform-origin

优点

  • 可以通过边框实现形状。
  • 尺寸不需要按比例增加以保持形状。

缺点

  • 内容也将被旋转,因此它们必须被反向旋转才能看起来正常。
  • 如果尺寸不是静态的,定位文本将是乏味的。

方法5 - CSS剪辑路径

(Qazxswpoi)

在该方法中,使用多边形将主容器剪切成所需的形状。应根据需要倾斜边的一侧修改多边形的点。

transform-origin
$(document).ready(function() {
  $('#increasew-rotate').on('click', function() {
    $('.rotate').css({
      'height': '100px',
      'width': '150px'
    });
  });
  $('#increaseh-rotate').on('click', function() {
    $('.rotate').css({
      'height': '150px',
      'width': '100px'
    });
  });
  $('#increaseb-rotate').on('click', function() {
    $('.rotate').css({
      'height': '150px',
      'width': '150px'
    });
  });
})
div {
  float: left;
  height: 100px;
  width: 100px;
  margin: 50px;
  color: beige;
  transition: all 1s;
}
.rotate {
  position: relative;
  width: 100px;
  background: tomato;
}
.rotate.bottom {
  transform-origin: top;
  transform: perspective(10px) rotateY(-2deg);
}
.rotate.top {
  transform-origin: bottom;
  transform: perspective(10px) rotateY(-2deg);
}
.rotate.left {
  transform-origin: right;
  transform: perspective(10px) rotateX(-2deg);
}
.rotate.right {
  transform-origin: left;
  transform: perspective(10px) rotateX(-2deg);
}
.rotate span {
  position: absolute;
  display: block;
  top: 0px;
  right: 0px;
  width: 50%;
  height: 100%;
}
.rotate.bottom span {
  padding: 10px;
  transform-origin: top;
  transform: perspective(10px) rotateY(2deg);
}
.rotate.top span {
  padding: 20px;
  transform-origin: bottom;
  transform: perspective(20px) rotateY(2deg);
}
.rotate.left span {
  padding: 10px;
  transform-origin: right;
  transform: perspective(10px) rotateX(2deg);
}
.rotate.right span {
  padding: 0px 30px;
  transform-origin: left;
  transform: perspective(10px) rotateX(2deg);
}
.rotate:hover {
  background: steelblue;
}

/* Just for demo */

body {
  background: radial-gradient(circle at 50% 50%, aliceblue, steelblue);
}
.rotate.left{
  clear:both;
}
.btn-container {
  position: absolute;
  top: 0px;
  right: 0px;
  width: 150px;
}
button {
  width: 150px;
  margin-bottom: 10px;
}

优点

  • 即使在动态调整容器大小时,也可以保持形状。
  • 悬浮效果将完全限制在形状的边界内。
  • 图像也可以用作形状的背景。

缺点

  • 浏览器支持目前很差。
  • 可以通过将绝对定位的元素放置在形状的顶部并为其提供必要的剪辑来添加边框,但是在动态重新调整大小时它不适合。

方法6 - 画布

(Qazxswpoi)

Canvas也可用于通过绘制路径来生成形状。下面的代码片段有一个演示。所需的任何文本内容都可以定位在形状的顶部。

<script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="rotate bottom"><span>Some content</span>
</div>
<div class="rotate top"><span>Some content</span>
</div>
<div class="rotate left"><span>Some content</span>
</div>
<div class="rotate right"><span>Some content</span>
</div>

<div class='btn-container'>
  <button id="increasew-rotate">Increase Width</button>
  <button id="increaseh-rotate">Increase Height</button>
  <button id="increaseb-rotate">Increase Both</button>
</div>
Browser Compatibility
$(document).ready(function() {
  $('#increasew-clip').on('click', function() {
    $('.clip-path').css({
      'height': '100px',
      'width': '150px'
    });
  });
  $('#increaseh-clip').on('click', function() {
    $('.clip-path').css({
      'height': '150px',
      'width': '100px'
    });
  });
  $('#increaseb-clip').on('click', function() {
    $('.clip-path').css({
      'height': '150px',
      'width': '150px'
    });
  });
})

优点

  • 即使容器的尺寸是动态的,也可以实现和保持形状。边界也可以添加。
  • 可以使用.clip-path { position: relative; float: left; margin: 20px; height: 100px; width: 100px; background: tomato; padding: 4px; transition: all 1s; } .clip-path.bottom { -webkit-clip-path: polygon(0% 0%, 100% 0%, 100% 100%, 0% 60%); } .clip-path.top { -webkit-clip-path: polygon(0% 40%, 100% 0%, 100% 100%, 0% 100%); } .clip-path.left { -webkit-clip-path: polygon(0% 0%, 100% 0%, 100% 100%, 40% 100%); } .clip-path.right { -webkit-clip-path: polygon(0% 0%, 60% 0%, 100% 100%, 0% 100%); } .clip-path .content { position: absolute; content: ''; height: calc(100% - 10px); width: calc(100% - 8px); background: bisque; } .clip-path.bottom .content { -webkit-clip-path: polygon(0% 0%, 100% 0%, 100% 100%, 0% 60%); } .clip-path.top .content { -webkit-clip-path: polygon(0% 40%, 100% 0%, 100% 100%, 0% 100%); } .clip-path .content.img { top: 6px; background: url(http://lorempixel.com/250/250); background-size: 100% 100%; } /* Just for demo */ body { background: radial-gradient(circle at 50% 50%, aliceblue, steelblue); } .clip-path.left { clear: both; } .clip-path:hover { background: gold; } .btn-container { position: absolute; top: 0px; right: 0px; margin: 20px; width: 150px; } button { width: 150px; margin-bottom: 10px; }方法将悬停效果限制在形状边界内。
  • 还可以向形状提供图像或梯度背景。
  • 如果需要实时动画效果,则更好的选择,因为它不需要DOM操作。

缺点

  • Canvas是基于栅格的,因此当缩放超过点*时,成角度的边缘将变为像素化或模糊。

* - 每当调整视口大小时,避免像素化都需要重新绘制形状。有一个例子,它<script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script> <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <div class="clip-path bottom"> <div class="content">abcd</div> </div> <div class="clip-path top"> <div class="content img"></div> </div> <div class="clip-path left"></div> <div class="clip-path right"></div> <div class='btn-container'> <button id="increasew-clip">Increase Width</button> <button id="increaseh-clip">Increase Height</button> <button id="increaseb-clip">Increase Both</button> </div>但这是一个开销。


34
投票

我尝试使用border方法,但我的形状的尺寸是动态的,因此我不能使用这种方法。


方法7 - 视口单元(Border Redux)

(Qazxswpoi)

Browser Compatibility是CSS3的一项伟大创新。虽然您通常可以使用百分比值来动态化您的属性,但您无法为window.onload = function() { var canvasEls = document.getElementsByTagName('canvas'); for (var i = 0; i < canvasEls.length; i++) { paint(canvasEls[i]); } function paint(canvas) { var ctx = canvas.getContext('2d'); ctx.beginPath(); if (canvas.className == 'bottom') { ctx.moveTo(0, 0); ctx.lineTo(250, 0); ctx.lineTo(250, 100); ctx.lineTo(0, 60); } else if (canvas.className == 'top') { ctx.moveTo(0, 40); ctx.lineTo(250, 0); ctx.lineTo(250, 100); ctx.lineTo(0, 100); } else if (canvas.className == 'left') { ctx.moveTo(0, 0); ctx.lineTo(250, 0); ctx.lineTo(250, 100); ctx.lineTo(60, 100); } else if (canvas.className == 'right') { ctx.moveTo(0, 0); ctx.lineTo(190, 0); ctx.lineTo(250, 100); ctx.lineTo(0, 100); } ctx.closePath(); ctx.lineCap = 'round'; ctx.fillStyle = 'tomato'; ctx.fill(); } $('#increasew-canvas').on('click', function() { $('.container').css({ 'width': '150px', 'height': '100px' }); }); $('#increaseh-canvas').on('click', function() { $('.container').css({ 'width': '100px', 'height': '150px' }); }); $('#increaseb-canvas').on('click', function() { $('.container').css({ 'width': '150px', 'height': '150px' }); }); };s(.container { float: left; position: relative; height: 100px; width: 100px; margin: 20px; color: beige; transition: all 1s; } canvas { height: 100%; width: 100%; } .container > span { position: absolute; top: 5px; left: 5px; padding: 5px; } .top + span { top: 40%; /* size of the angled area */ } .left + span { left: 40%; /* size of the angled area */ } /* Just for demo */ body { background: radial-gradient(circle at 50% 50%, aliceblue, steelblue); } .btn-container { position: absolute; top: 0px; right: 0px; width: 150px; } button { width: 150px; margin-bottom: 10px; } div:nth-of-type(3) { clear: both; })执行此操作。

与视口尺寸相比,使用视口单元而不是<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script> <div class="container"> <canvas height="100px" width="250px" class="bottom"></canvas> <span>Some content</span> </div> <div class="container"> <canvas height="100px" width="250px" class="top"></canvas> <span>Some content</span> </div> <div class="container"> <canvas height="100px" width="250px" class="left"></canvas> <span>Some content</span> </div> <div class="container"> <canvas height="100px" width="250px" class="right"></canvas> <span>Some content</span> </div> <div class='btn-container'> <button id="increasew-canvas">Increase Width</button> <button id="increaseh-canvas">Increase Height</button> <button id="increaseb-canvas">Increase Both</button> </div>以及对象的大小。

注意:百分比值是指父对象,而不是视口(窗口的可见区域)。

要测试该方法,请启动以下片段“整页”并水平和垂直调整其大小。

pointInpath
here

优点 - (1)一切都是动态的,浏览器覆盖范围很广。

缺点 - (1)你应该注意Browser CompatibilityViewport Units


-1
投票

border-width的灵感来自本页上方的Andrea Ligios方法7 - 视口单元。

当调整导航窗口的宽度时,我也使用“水平”单位作为高度(nor for font-sizes)以保持给定比例在梯形中。我们可以称之为方法7b - 视口宽度。

此外,在我看来,使用两个嵌套的you can dynamically set your border widthss而不是一个和.shape { position: relative; height: 20vh; width: 40vw; background: tomato; } .shape:after { position: absolute; content: ''; left: 0px; right: 0px; top: 20vh; border-width: 10vh 20vw; border-style: solid; border-color: tomato tomato rgba(0,0,0,0) rgba(0,0,0,0); }选择器,可以更好地调整文本内容样式(例如<div class="shape">Some content</div>等)。

© www.soinside.com 2019 - 2024. All rights reserved.