是否可以使用 CSS 变换将 HTML 元素倾斜多个像素?
Is it possible to skew HTML element by a number of pixels using CSS transform?
我的问题是:
有一个包含可变数量 HTML 元素的块。像这样...
<ul class="list">
<li class="item">...</li>
<li class="item">...</li>
<li class="item">...</li>
</ul>
此块右侧必须有倾斜(内容不得倾斜)。这种倾斜的水平尺寸必须是固定的。所以添加 CSS 规则,例如...
.list {
position: relative;
background: #A0A0FF;
}
.list:after {
content: " ";
display: block;
position: absolute;
top: 0;
bottom: 0;
right: -10px;
width: 20px;
transform: skewX(-15deg);
background: #A0A0FF;
}
...不会这样做,因为在这种情况下,倾斜将具有可变的水平大小,具体取决于列表中的项目数。我想到的唯一解决方案是在js中计算度数。但这有点无聊。
所以我的问题是:是否可以使用 CSS 以某种方式将元素倾斜多个像素而不是 degrees/radians?
我不知道你在找什么,但这就是你在找的吗?
.list {
position: relative;
background-color: yellow;
}
.list:after {
content: " ";
display: block;
position: absolute;
background-color: blue;
top: 0;
bottom: 0;
right: 10px;
width: 20px;
transform: skewX(-15deg);
}
<ul class="list">
<li class="item">...</li>
<li class="item">...</li>
<li class="item">...</li>
</ul>
您可以通过在伪元素上使用线性渐变来实现相同的 skew
外观。
*,
::after,
::before {
box-sizing: border-box;
margin: 0;
padding: 0;
}
ul {
width: 200px;
background: #663399;
margin: 25px auto;
list-style-type: none;
position: relative;
}
ul::after {
position: absolute;
content: "";
top: 0;
left: 100%;
background: linear-gradient(to bottom right, #663399 0%, #663399 50%, transparent 50%, transparent 100%);
width: 16px;
height: 100%;
}
<ul class="list">
<li class="item">...</li>
<li class="item">...</li>
<li class="item">...</li>
</ul>
<ul class="list">
<li class="item">...</li>
<li class="item">...</li>
<li class="item">...</li>
<li class="item">...</li>
<li class="item">...</li>
<li class="item">...</li>
</ul>
抱歉,如果我的消息与这个确切的案例无关,但是一旦我搜索了 "CSS skew in pixels",尽管这个问题都不是关于我的试图找到 (以像素为单位提供要倾斜的确切宽度),接受的答案也没有解决我的问题,我仍然相信这有一天可以帮助某人。
我们知道,transform: skew()
仅接收角度作为参数。
为了在角度未知时获得准确的宽度,应该使用反正切来计算角度。幸运的是,JavaScript 1.0 Math
提供 atan2() 方法来 return 给定 X 和 Y 坐标的反正切(以弧度为单位)。
这样,计算倾斜角度在JS上就有了解决办法。
The example below 根据底层元素的尺寸绘制对角线(通过 border-bottom
/border-left
)。
let prevY = null;
document.querySelectorAll('.a').forEach(el => {
const top = el.style.top;
const left = el.style.left;
const width = el.style.width;
const height = el.style.height;
const xEl = document.querySelector('#x' + el.id.substr(1));
xEl.style.top = top;
xEl.style.left = left;
xEl.style.width = width;
xEl.style.height = height;
applySkew(el);
});
window.addEventListener('resize', function(e) {
prevY = null;
document.querySelectorAll('.a').forEach(el => {
applySkew(el);
});
});
function applySkew(el) {
const xEl = document.querySelector('#x' + el.id.substr(1));
const top = el.style.top;
const w = el.offsetWidth;
const h = el.offsetHeight;
const directionUp = prevY && prevY != top;
prevY = top;
if(w < h) {
xEl.style.borderBottom = 'none';
xEl.style.borderLeft = 'black 1px solid';
xEl.style.transform = 'skewX(' + Math.atan2((directionUp ? -1 : 1) * w, h) + 'rad) translateX(' + (w / 2) + 'px)';
} else {
xEl.style.borderLeft = 'none';
xEl.style.borderBottom = 'black 1px solid';
xEl.style.transform = 'skewY(' + Math.atan2((directionUp ? -1 : 1) * h, w) + 'rad) translateY(-' + (h / 2) + 'px)';
}
}
html, body {
margin: 0;
height: 100%;
}
body > div {
margin: 5% 0 0 5%;
background: yellow;
position: relative;
height: 40%;
width: 90%;
}
body > div > div {
position: absolute;
box-sizing: border-box;
}
<div>
<div id="a0" class="a" style="
top: 0;
left: 0;
width: 7.5%;
height: 70%;
background-color: rgba(0,255,255,.5);
"></div>
<div id="a1" class="a" style="
top: 40%;
left: 7.5%;
width: 17.5%;
height: 30%;
background-color: rgba(0,255,255,.2);
"></div>
<div id="a2" class="a" style="
top: 40%;
left: 25%;
width: 37%;
height: 55%;
background-color: rgba(0,255,255,.4);
"></div>
<div id="a3" class="a" style="
top: 25%;
left: 62%;
width: 3%;
height: 70%;
background-color: rgba(0,255,255,.1);
"></div>
<div id="a4" class="a" style="
top: 25%;
left: 65%;
width: 35%;
height: 50%;
background-color: rgba(0,255,255,.6);
"></div>
<div id="x0"></div>
<div id="x1"></div>
<div id="x2"></div>
<div id="x3"></div>
<div id="x4"></div>
</div>
我的问题是: 有一个包含可变数量 HTML 元素的块。像这样...
<ul class="list">
<li class="item">...</li>
<li class="item">...</li>
<li class="item">...</li>
</ul>
此块右侧必须有倾斜(内容不得倾斜)。这种倾斜的水平尺寸必须是固定的。所以添加 CSS 规则,例如...
.list {
position: relative;
background: #A0A0FF;
}
.list:after {
content: " ";
display: block;
position: absolute;
top: 0;
bottom: 0;
right: -10px;
width: 20px;
transform: skewX(-15deg);
background: #A0A0FF;
}
...不会这样做,因为在这种情况下,倾斜将具有可变的水平大小,具体取决于列表中的项目数。我想到的唯一解决方案是在js中计算度数。但这有点无聊。
所以我的问题是:是否可以使用 CSS 以某种方式将元素倾斜多个像素而不是 degrees/radians?
我不知道你在找什么,但这就是你在找的吗?
.list {
position: relative;
background-color: yellow;
}
.list:after {
content: " ";
display: block;
position: absolute;
background-color: blue;
top: 0;
bottom: 0;
right: 10px;
width: 20px;
transform: skewX(-15deg);
}
<ul class="list">
<li class="item">...</li>
<li class="item">...</li>
<li class="item">...</li>
</ul>
您可以通过在伪元素上使用线性渐变来实现相同的 skew
外观。
*,
::after,
::before {
box-sizing: border-box;
margin: 0;
padding: 0;
}
ul {
width: 200px;
background: #663399;
margin: 25px auto;
list-style-type: none;
position: relative;
}
ul::after {
position: absolute;
content: "";
top: 0;
left: 100%;
background: linear-gradient(to bottom right, #663399 0%, #663399 50%, transparent 50%, transparent 100%);
width: 16px;
height: 100%;
}
<ul class="list">
<li class="item">...</li>
<li class="item">...</li>
<li class="item">...</li>
</ul>
<ul class="list">
<li class="item">...</li>
<li class="item">...</li>
<li class="item">...</li>
<li class="item">...</li>
<li class="item">...</li>
<li class="item">...</li>
</ul>
抱歉,如果我的消息与这个确切的案例无关,但是一旦我搜索了 "CSS skew in pixels",尽管这个问题都不是关于我的试图找到 (以像素为单位提供要倾斜的确切宽度),接受的答案也没有解决我的问题,我仍然相信这有一天可以帮助某人。
我们知道,transform: skew()
仅接收角度作为参数。
为了在角度未知时获得准确的宽度,应该使用反正切来计算角度。幸运的是,JavaScript 1.0 Math
提供 atan2() 方法来 return 给定 X 和 Y 坐标的反正切(以弧度为单位)。
这样,计算倾斜角度在JS上就有了解决办法。
The example below 根据底层元素的尺寸绘制对角线(通过 border-bottom
/border-left
)。
let prevY = null;
document.querySelectorAll('.a').forEach(el => {
const top = el.style.top;
const left = el.style.left;
const width = el.style.width;
const height = el.style.height;
const xEl = document.querySelector('#x' + el.id.substr(1));
xEl.style.top = top;
xEl.style.left = left;
xEl.style.width = width;
xEl.style.height = height;
applySkew(el);
});
window.addEventListener('resize', function(e) {
prevY = null;
document.querySelectorAll('.a').forEach(el => {
applySkew(el);
});
});
function applySkew(el) {
const xEl = document.querySelector('#x' + el.id.substr(1));
const top = el.style.top;
const w = el.offsetWidth;
const h = el.offsetHeight;
const directionUp = prevY && prevY != top;
prevY = top;
if(w < h) {
xEl.style.borderBottom = 'none';
xEl.style.borderLeft = 'black 1px solid';
xEl.style.transform = 'skewX(' + Math.atan2((directionUp ? -1 : 1) * w, h) + 'rad) translateX(' + (w / 2) + 'px)';
} else {
xEl.style.borderLeft = 'none';
xEl.style.borderBottom = 'black 1px solid';
xEl.style.transform = 'skewY(' + Math.atan2((directionUp ? -1 : 1) * h, w) + 'rad) translateY(-' + (h / 2) + 'px)';
}
}
html, body {
margin: 0;
height: 100%;
}
body > div {
margin: 5% 0 0 5%;
background: yellow;
position: relative;
height: 40%;
width: 90%;
}
body > div > div {
position: absolute;
box-sizing: border-box;
}
<div>
<div id="a0" class="a" style="
top: 0;
left: 0;
width: 7.5%;
height: 70%;
background-color: rgba(0,255,255,.5);
"></div>
<div id="a1" class="a" style="
top: 40%;
left: 7.5%;
width: 17.5%;
height: 30%;
background-color: rgba(0,255,255,.2);
"></div>
<div id="a2" class="a" style="
top: 40%;
left: 25%;
width: 37%;
height: 55%;
background-color: rgba(0,255,255,.4);
"></div>
<div id="a3" class="a" style="
top: 25%;
left: 62%;
width: 3%;
height: 70%;
background-color: rgba(0,255,255,.1);
"></div>
<div id="a4" class="a" style="
top: 25%;
left: 65%;
width: 35%;
height: 50%;
background-color: rgba(0,255,255,.6);
"></div>
<div id="x0"></div>
<div id="x1"></div>
<div id="x2"></div>
<div id="x3"></div>
<div id="x4"></div>
</div>