我正在尝试创建如下图所示的形状,仅在一侧(例如,底侧)具有倾斜的边缘,而其他边缘保持笔直。
我尝试使用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>
如何创建具有倾斜侧面的形状,并且还能够支持动态尺寸?
有很多方法可以创建仅在一侧具有倾斜边缘的形状。
正如问题中已经提到的,以下方法不能支持动态大小:
border-width
方法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); /* 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; }
<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>
优点
缺点
方法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); /* 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>
悬停效果可以通过更改渐变颜色来添加。 缺点
即使光标在形状之外但在容器内,也会触发悬停效果。
方法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; } /* 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>
悬停效果将限于形状内。 缺点
为了使形状保持不变,尺寸需要成比例地增加,因为当元素倾斜时,其在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; } /* 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; }
<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>
方法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%; } /* 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; }
<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>
图像也可以用作形状的背景。 缺点
目前浏览器支持非常差。
方法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%; /* 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>