有很多方法可以创建仅在一侧具有倾斜边缘的形状。
正如问题中已经提到的,以下方法不能支持动态大小:
- 具有像素值的边界三角法
border-width
。 - 具有角度语法的线性渐变(例如45deg,30deg等)。
可以支持动态大小的方法如下所述。
方法1-SVG
可以使用polygons或paths 来使用SVG产生形状。以下代码段使用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); left: 5px; }.vector.bottom > span{ height: 50%; width: 100%; top: 5px; left: 5px; }.vector.left > span{ width: 50%; height: 100%; left: 50%; top: 5px; }.vector.right > span{ width: 50%; height: 100%; left: 5px; top: 5px; }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;}<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 > <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 > <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 > <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 > <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 > <button id="increasew-vector">Increase Width</button> <button id="increaseh-vector">Increase Height</button> <button id="increaseb-vector">Increase Both</button></div>
优点
- SVG旨在产生可扩展的图形,并且可以很好地应对所有尺寸变化。
- 可以以最小的编码开销实现边界和悬停效果。
- 图像或渐变背景也可以提供给形状。
缺点
- 浏览器支持可能是唯一的缺点,因为IE8不支持SVG,但可以通过使用Raphael和VML之类的库来缓解这种情况。而且,浏览器支持丝毫不比其他选项差。
方法2-渐变背景
(
线性渐变仍然可以用来生成形状,但不能像问题中提到的那样使用角度。我们必须使用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' }); });})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); left: 5px; height: 50%;}.gradient.bottom span{ top: 5px; left: 5px; height: 50%;}.gradient.left span{ left: 40%; top: 5px; width: 50%;}.gradient.right span{ left: 5px; top: 5px; width: 50%;}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 ><span>Some content</span></div><div ><span>Some content</span></div><div ><span>Some content</span></div><div ><span>Some content</span></div><div > <button id="increasew-gradient">Increase Width</button> <button id="increaseh-gradient">Increase Height</button> <button id="increaseb-gradient">Increase Both</button></div>
优点
- 即使容器的尺寸是动态的,也可以实现并保持形状。
悬停效果可以通过更改渐变颜色来添加。
缺点即使光标在形状之外但在容器内,也会触发悬停效果。
- 添加边框将需要棘手的渐变操作。
- 当宽度(或高度)很大时,渐变会产生锯齿状的角。
- 图像背景不能在形状上使用。
方法3-偏斜变换
在这种方法中,添加,倾斜和定位伪元素的方式应使其看起来像其中一个边缘是倾斜/倾斜的。如果顶部或底部边缘是倾斜的,则倾斜应沿Y轴,否则旋转应沿X轴。本transform-origin应具备的相反侧倾斜侧。
$(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;}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 >Some content</div><div >Some content</div><div >Some content</div><div >Some content</div><div > <button id="increasew-skew">Increase Width</button> <button id="increaseh-skew">Increase Height</button> <button id="increaseb-skew">Increase Both</button></div>
优点
- 即使有边框也可以实现形状。
悬停效果将限于形状内。
缺点为了使形状保持不变,尺寸需要成比例地增加,因为当元素倾斜时,其在Y轴上的偏移会随着width增加而增加,反之亦然(尝试将其width增加到200pxsnippet中)。您可以在此处找到有关此信息的更多信息。
方法4-透视变换
在这种方法中,主容器沿X轴或Y轴旋转会有一点透视。将适当的值设置为transform-origin只会在一侧产生倾斜的边缘。
如果顶部或底部倾斜,则旋转应沿Y轴,否则旋转应沿X轴。本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;}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;}<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 ><span>Some content</span></div><div ><span>Some content</span></div><div ><span>Some content</span></div><div ><span>Some content</span></div><div > <button id="increasew-rotate">Increase Width</button> <button id="increaseh-rotate">Increase Height</button> <button id="increaseb-rotate">Increase Both</button></div>
优点
- 可以通过边框实现形状。
- 尺寸不必成比例地增加即可保持形状。
缺点
- 内容也会旋转,因此必须反向旋转才能看起来正常。
- 如果尺寸不是静态的,则定位文本将很乏味。
方法5-CSS剪切路径
(浏览器兼容性)
在这种方法中,使用多边形将主容器裁剪为所需的形状。多边形的点应根据需要倾斜边的一侧进行修改。
$(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%;}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;}<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 > <div >abcd</div></div><div > <div ></div></div><div ></div><div ></div><div > <button id="increasew-clip">Increase Width</button> <button id="increaseh-clip">Increase Height</button> <button id="increaseb-clip">Increase Both</button></div>
优点
- 即使动态调整容器大小也可以保持形状。
- 悬停效果将完全限制在形状的边界内。
图像也可以用作形状的背景。
缺点目前浏览器支持非常差。
- 可以通过以下方式添加边框:将绝对定位的元素放置在形状的顶部,并为其提供必要的剪辑,但是超出某个点时,它在动态调整大小时不太适合。
方法6-画布
画布也可以用于通过绘制路径来生成形状。下面的代码片段有一个演示。所需的任何文本内容都可以放置在图形的顶部。
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' }); });};.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%; }.left + span { left: 40%; }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 > <canvas height="100px" width="250px" ></canvas> <span>Some content</span></div><div > <canvas height="100px" width="250px" ></canvas> <span>Some content</span></div><div > <canvas height="100px" width="250px" ></canvas> <span>Some content</span></div><div > <canvas height="100px" width="250px" ></canvas> <span>Some content</span></div><div > <button id="increasew-canvas">Increase Width</button> <button id="increaseh-canvas">Increase Height</button> <button id="increaseb-canvas">Increase Both</button></div>
优点
- 即使容器的尺寸是动态的,也可以实现并保持形状。也可以添加边框。
- 使用pointInpath方法可以将悬停效果限制在形状的边界内。
- 图像或渐变背景也可以提供给形状。
- 如果需要实时动画效果,因为它不需要DOM操作,因此是更好的选择。
缺点
- 画布基于栅格,因此,缩放到超过点时,倾斜的边缘将变得像素化或模糊。
-调整视口大小时,避免像素化将需要重新绘制形状。有它的一个例子在这里,但是这是一个开销。



