侧面倾斜的形状(响应式)
Posted
技术标签:
【中文标题】侧面倾斜的形状(响应式)【英文标题】:Shape with a slanted side (responsive) 【发布时间】:2015-08-07 02:22:10 【问题描述】:我正在尝试创建一个如下图所示的形状,仅在一侧具有倾斜边缘(例如,底侧),而其他边缘保持笔直。
我尝试使用边框方法(代码如下),但我的形状尺寸是动态的,因此我不能使用这种方法。
.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>
我也尝试过使用渐变作为背景(如下面的代码),但随着尺寸的变化,它会变得混乱。您可以通过将鼠标悬停在下面 sn-p 中的形状上来了解我的意思。
.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>
我怎样才能创建这种带有倾斜边的形状,并且还能够支持动态尺寸?
【问题讨论】:
【参考方案1】:My solution 的灵感来自 Andrea Ligios 的 Method 7 - Viewport Units,位于本页上方。
在调整导航窗口的宽度时,我也使用“水平”单位作为高度 (height:10vw
) 以保持梯形中的给定比例。我们可以称之为方法 7b - 视口宽度。
此外,在我看来,使用两个嵌套的div
s,而不是一个和:after
选择器,可以更好地调整文本内容样式(例如text-align
等)。
.dtrapz
position: relative;
margin: 10px 40vw;
width: 0;
height: 10vw;
border: none;
border-right: 20vw solid #f22;
border-bottom: 5vw solid transparent;
.dtcont
position: absolute;
width: 20vw;
height: 10vw;
text-align: center;
color: #fff;/* just aesthetic */
<div class="dtrapz">
<div class="dtcont">Some content</div>
</div>
【讨论】:
@Downvoter 嗨!让我知道我的答案有什么问题,因此如果有意义,我可以编辑或删除它!我不是专家,但在我看来,这可以应用于许多页面,处理更长的文本内容,仅取决于宽度:)【参考方案2】:我尝试使用 border 方法,但我的形状尺寸是动态的,因此我无法使用此方法。
方法 7 - 视口单位 (Border Redux)
(Browser Compatibility)
Viewport Units 是 CSS3 的一大创新。虽然您通常可以使用百分比值来动态化您的属性,但对于 border-width
s (nor for font-size
s),您不能这样做。
使用视口单位而不是 you can dynamically set your border widths,以及与视口尺寸相比的对象大小。
注意:百分比值是指父对象,而不是视口(窗口的可见区域)。
要测试该方法,请启动以下 sn -p 整页并在水平和垂直方向上调整其大小。
.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>
优点 - (1) 一切都是动态的,浏览器覆盖范围很广。
缺点 - (1) 你应该注意how your OS handles the scrollbar 和overflow: auto;
。
【讨论】:
在最新版本的 chrome 中看起来参差不齐。 真的!我猜浏览器引擎仍然需要一些时间才能顺利渲染。 Firefox 在将这种技术与像素而不是视口单位一起使用时也存在这个问题,但可以通过使用 rgba(,,,0) 而不是透明来解决。幸运的是,我们现在还有其他选择;)【参考方案3】:有很多方法可以创建仅在一侧具有倾斜边缘的形状。
以下方法不支持问题中已经提到的动态尺寸:
像素值为border-width
的边界三角形法。
具有角度语法的线性渐变(如 45 度、30 度等)。
下面介绍了可以支持动态尺寸的方法。
方法 1 - SVG
(Browser Compatibility)
SVG 可用于通过polygon
s 或path
s 生成形状。下面的 sn-p 使用了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>
优点
SVG 旨在生成可缩放的图形,并且可以很好地适应所有尺寸变化。 可以以最小的编码开销实现边框和悬停效果。 还可以为形状提供图像或渐变背景。缺点
浏览器支持可能是唯一的缺点,因为 IE8- 不支持 SVG,但可以通过使用 Raphael 和 VML 等库来缓解这种情况。此外,浏览器支持绝不比其他选项差。方法 2 - 渐变背景
(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'
);
);
)
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 - 倾斜变换
(Browser Compatibility)
在此方法中,添加、倾斜和定位伪元素,使其看起来像其中一个边缘倾斜/倾斜。如果顶部或底部边缘倾斜,则倾斜应沿 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
的增加而增加,反之亦然(尝试在sn-p)。您可以找到有关此here 的更多信息。
方法 4 - 透视变换
(Browser Compatibility)
在这种方法中,主容器沿 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 剪辑路径
(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;
<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 - 画布
(Browser Compatibility)
Canvas 也可用于通过绘制路径来生成形状。下面的 sn-p 有一个演示。所需的任何文本内容都可以放置在形状的顶部。
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 class="bottom"></canvas> <span>Some content</span>
</div>
<div class="container">
<canvas class="top"></canvas> <span>Some content</span>
</div>
<div class="container">
<canvas class="left"></canvas> <span>Some content</span>
</div>
<div class="container">
<canvas 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
方法将悬停效果限制在形状的边界内。
还可以为形状提供图像或渐变背景。
如果需要实时动画效果是更好的选择,因为它不需要 DOM 操作。
缺点
画布是基于光栅的,因此当缩放超出点 * 时,倾斜的边缘会变得像素化或模糊。* - 每当调整视口大小时,避免像素化需要重新绘制形状。有一个例子here,但这是一个开销。
【讨论】:
以上是关于侧面倾斜的形状(响应式)的主要内容,如果未能解决你的问题,请参考以下文章