【问题标题】:Is it possible to skew HTML element by a number of pixels using CSS transform?是否可以使用 CSS 转换将 HTML 元素倾斜多个像素?
【发布时间】:2015-04-17 02:03:22
【问题描述】:

我的问题是: 有一个包含可变数量的 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 以某种方式将元素倾斜多个像素而不是度数/弧度?

【问题讨论】:

  • 那个 CSS does 歪曲了 .list:after 伪元素——当然,那个元素的内容只是一个空格,所以你可能看不到它确实......
  • 否...skew 需要一个“角度”值。 - Skew @ MDN
  • 你有这应该是什么样子的图像吗?

标签: javascript css css-transforms


【解决方案1】:

对不起,如果我的消息与这个确切的情况无关,但是一旦我搜索了 “CSS skew in pixel”,尽管这个问题都不是关于我试图找到的 (提供以 px 为单位的精确宽度倾斜),接受的答案也不能解决我的问题,我仍然相信有一天这可以帮助某人。

我们知道,transform: skew() 只接收角度作为参数。 为了在角度未知时得到准确的宽度,应该使用反正切来计算角度。幸运的是,JavaScript 1.0 Math 提供了 atan2() 方法来返回给定 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;
}
&nbsp;
<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>

【讨论】:

    【解决方案2】:

    您可以通过在伪元素上使用线性渐变来实现相同的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>

    【讨论】:

      【解决方案3】:

      我不知道你在追求什么,但这就是你在寻找的东西吗?

      .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>

      【讨论】:

      • 没有。我需要一个固定水平尺寸的倾斜。正如我在帖子中所写的那样,您发布的 CSS 将导致水平大小可变的倾斜,因为在我的情况下,列表中的元素数量是可变的。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-05-18
      • 1970-01-01
      • 1970-01-01
      • 2021-05-17
      • 1970-01-01
      • 2012-01-04
      • 1970-01-01
      相关资源
      最近更新 更多