根据元素的高度和宽度,转换X和Y百分比值?

102

将元素的Y轴移动50%会将其下移自身高度的50%,而不是像我所期望的那样基于父元素的高度移动50%。我如何告诉一个正在移动的元素以父元素为基础计算其百分比偏移量?还是说我没有理解正确?

http://jsfiddle.net/4wqEm/2/


7
好的,看起来这是无法避免的。按百分比进行CSS翻译时,它会取被翻译元素的%来计算移动的距离。它不像typical的css声明如top、margin-top或padding-top,这些都是基于父容器的。 - Andrew Tibbetts
1
谢谢,一开始我并不清楚百分比值是相对于什么的。 - Philip Walton
4
下一步,你会发现他们也会让百分比表示字体大小的百分比!(哦...) - Kevin Peno
10个回答

53
当在非SVG元素上使用百分比的transform translate时,它指的是自身的宽度或高度。请查看https://davidwalsh.name/css-vertical-center (demo)。
CSS transform 的一个有趣之处是,当使用百分比值应用于 CSS transform 时,它们基于被实现的元素的尺寸来计算该值,而不是像 top、right、bottom、left、margin 和 padding 这些属性,这些属性只使用父元素的尺寸(或在绝对定位的情况下,使用最近的相对父元素)。
在 SVG 元素上,transform 百分比则是指父级的大小!
这里有一个示例:

https://codepen.io/trusktr/pen/gOdwWXv

svg, [outer] {
  border: 1px solid black;
}

rect {
  transform: translate3d(50%, 50%, 0);
}

[inner] {
  background: black;
  transform: translate3d(50%, 50%, 0);
}
<svg width="100" height="80">
    <rect width="20" height="20" />
</svg>

<div outer style="width: 100px; height: 80px;">
    <div inner style="width: 20px; height: 20px;"></div>
</div>

奇怪,嗯?

4
在对SVG进行动画处理时,transform: translate(50%)似乎使用了父元素的宽度和高度。 - Atav32
@Atav32 这确实是一件奇怪的事情。他们应该给我们两个选项,停止这种奇怪的操作。 - trusktr

26

您可以使用vw和vh根据视口大小进行转换

@keyframes bubbleup {
  0% {
    transform: translateY(100vh);
  }

  100% {
    transform: translateY(0vh);
  }
}

这对我不起作用... vh ~40 就像页面底部吗?! - AturSams
我的错...元素不在绝对元素内... :) - AturSams
24
@AxeEffect 这个回答不应被接受。它是基于视口而非父元素的大小来计算的。如果父元素的大小不是视口的全尺寸,那该怎么办? - trusktr
@wolfdawn 如果你使用缩放,顺序很重要。因此,“scale(1.5)translateY(40vw)”与“translateY(40vw)scale(1.5)”不同。 - Kardaw
1
你应该知道,苹果和谷歌在移动浏览器中破坏了vh单位,因此在这种情况下它是不可靠的。 - Kev

22

对我有效的,只使用纯 CSS的方法是:

.child {
    position: relative;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);

    /* Backward compatibility */
    -webkit-transform: translate(-50%, -50%);
    -moz-transform: translate(-50%, -50%);
    -o-transform: translate(-50%, -50%);
    -ms-transform: translate(-50%, -50%);
}

工作原理:

  • 通过顶部和左侧位置将子小部件移动到父级坐标。子小部件的上左角将恰好出现在父级的中心(这不是我们此时想要的)。
  • 根据其尺寸(而非父级),平移会将子小部件向上和向左移动50%。这意味着,小部件的中心点将被移动到之前设置为父级中心的上左点所在的位置,这正是我们想要的。

7

要在translate属性中使用百分比,您需要使用JavaScript:http://jsfiddle.net/4wqEm/27/

HTML代码:

<div id="parent">
    <div id="children"></div>
</div>​​​​​​​​​​​​​

CSS 代码:

#parent {
    width: 200px;
    height: 200px;
    background: #ff0;
}
#children {
    width: 10%;
    height: 10%;
    background: #f00;
}

Javascript 代码:

parent = document.getElementById('parent');
children = document.getElementById('children');

parent_height = parent.clientHeight;
​children_translate = parent_height * 50/100;
children.style.webkitTransform = "translateY("+children_translate+"px)";​​​​​​​​​​​​​​​​​​​​​​​​​​

我希望我能帮助您,如果您有其他问题,请告诉我。


2
我不能仅使用CSS3完成它吗? - Dchris

6
在支持的浏览器中,现在可以使用容器单位将元素按父元素宽度/高度的百分比进行翻译。
首先将父元素的容器类型属性设置为“大小”。这使得子元素可以查询父元素的尺寸。
.parent { container-type: size }

下面将使用cqh(容器查询高度)单位翻译子元素。1cqh等于父元素高度的1%。
/* shift child down by 50% of parent height */
.child { transform: translateY(50cqh) }

终于到了这一天。感谢克里斯提供了一个直接有效的解决方案,解决了确切的问题! - Andrew Tibbetts

4
你的说法在百分比来自于翻译元素方面是完全正确的。在你的情况下,应该使用绝对定位来保持相对于父div的位置,而不是使用翻译属性。我在这里垂直地绝对定位了你的红色div:(不要忘记在父div中添加相对定位。它必须被定位为非静态默认值)。 这里 是 js fiddle 的代码。
 body {
    margin: 0;
    width: 100%;
    height: 100%;
    }
 body > div {
    width: 200px;
    height: 200px;
    background: #ff0;
    position: relative;
    }
 body > div > div {
    width: 10%;
    height: 10%;
    -webkit-transform: translateY(-50%);
    background: #f00;
    position: absolute;
    top: 50%;
    }

2
但是动画化的上下和左右移动不是硬件加速的,对吧? - trusktr
@trusktr 是的,这取决于节点数量,最终会导致动画变得缓慢。 - m4heshd

4
你可以使用一个额外的块,对它进行过渡处理,而不包括子节点。
HTML代码:
<div id="parent">
    <div id="childrenWrapper">    
        <div id="children"></div>
    </div>
</div>​​​​​​​​​​​​​

CSS应该像这样:

#parent {
    position: relative;
    width: 200px;
    height: 200px;
    background: #ff0;
}
#childrenWrapper{
    width: 100%;
    height: 100%;
}
#children {
    width: 10%;
    height: 10%;
    background: #f00;
}

1

这是一个与定位相关的分支,需要在以下URL上进行定位: 工作样例

body {
margin: 0;
width: 100%;
height: 100%;
}

body>div {
position: relative;
width: 200px;
height: 200px;
background: #ff0;
}

body>div>div {
position: absolute;
left: 50%;
top: 50%;
width: 10%;
height: 10%;
background: #f00;
transform: translate(-50%, -50%);
}

注意:

  1. 您可以通过将父元素更改为相对定位来绝对定位红色正方形
  2. 然后使用50%的顶部和50%的左侧将根据其左上角位置红色正方形定位
  3. 使用transform:translate(-50%,-50%)将根据其中心位置红色正方形定位

0
这个问题的解决方案并不是使用翻译。当你翻译一个元素时,选择的百分比基于它自己的高度。
如果你想根据父元素的高度定位元素,请使用top: 50%;
所以代码将如下所示:
body {
    margin: 0;
    width: 100%;
    height: 100%;
}
body > div {
    width: 200px;
    height: 200px;
    background: #ff0;
    position: relative;
}
body > div > div {
    position: absolute;
    top: 50%;
    width: 10%;
    height: 10%;
/*     -webkit-transform: translateY(50%); */
    background: #f00;
}

0
你可以将元素设置为绝对定位,并使用left和top属性以百分比值作为父元素。

2
不建议使用。会导致动画运行缓慢。 - m4heshd

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接