对于奇数像素宽度,变换比例工作不正确 [英] transform scale works incorrectly for odd pixel widths

查看:116
本文介绍了对于奇数像素宽度,变换比例工作不正确的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我尝试调整div,但将内部元素保留在相同的位置相同的大小。为此,我使用wrapper和 transform:scale(1 / value)上的 transform:scale(value) on内部div。



问题是,当我改变比例尺时,里面的div会改变。只有当包装的宽度/高度是奇数或不全时才会发生。它不会发生在包装的宽度/高度上。



我的目标是让包装的许多子元素与包装物一起缩放,但只有一个不包含。



以下示例查看问题实际情况(悬停按比例缩放)。



strong>没有问题,内部元素停留在规模上(容器的高度和宽度均匀):



如果我们仅对容器应用比例,则会出现同样的问题。所以它不是因为内部元素的规模:

body:after {content:;位置:绝对; z-index:999; top:0;底部:-200%; width:2px;右:50%; margin-right:-1px;背景:rgba(0,0,0,0.5);}。box {width:200px; height:100px; margin:50px auto;背景:蓝色; position:relative;}。inner {height:20px; width:20px;背景:红色;位置:绝对;顶部:50%;剩下:50%; margin-left:-10px; text-align:center;颜色:#fff; margin-top:-10px;}

< div class =boxstyle =transform:scaleX(2)> < div class =inner> A< / div>< / div>< div class =boxstyle =width:201px; transform:scaleX(2)> < div class =inner> A< / div>< / div>






即使我们使用浮动价值与规模,我们可以说有一些roudering和复杂的计算,我们有正确的输出与偶数值和问题与奇数值:

具有比例的示例( 1.25)& scale(1 / 1.25):

body:after {content:;位置:绝对; z-index:999; top:0;底部:-200%; width:2px;右:50%; margin-right:-1px;背景:rgba(0,0,0,0.5);}。box {width:200px; height:100px; margin:50px auto;背景:蓝色; position:relative;}。inner {height:20px; width:20px;背景:红色;位置:绝对;顶部:50%;剩下:50%; margin-left:-10px; text-align:center;颜色:#fff; margin-top:-10px;}

< div class = 框 > < div class =inner> A< / div>< / div>< div class =boxstyle =transform:scaleX(1.25)> < div class =innerstyle =transform:scaleX(0.8)> A< / div>< / div>< div class =boxstyle =width:201px; transform:scaleX(1.25 )> < div class =innerstyle =transform:scaleX(0.8)> A< / div>< / div>



缩放比例(1.33)&比例尺(1 / 1.33):

body:after {content:;位置:绝对; z-index:999; top:0;底部:-200%; width:2px;右:50%; margin-right:-1px;背景:rgba(0,0,0,0.5);}。box {width:200px; height:100px; margin:50px auto;背景:蓝色; position:relative;}。inner {height:20px; width:20px;背景:红色;位置:绝对;顶部:50%;剩下:50%; margin-left:-10px; text-align:center;颜色:#fff; margin-top:-10px;}

< div class = 框 > < div class =inner> A< / div>< / div>< div class =boxstyle =transform:scaleX(1.33)> < div class =innerstyle =transform:scaleX(calc(1 / 1.33))> A< / div>< / div>< div class =boxstyle =width:201px;变换:将scaleX(1.33)> < div class =innerstyle =transform:scaleX(calc(1 / 1.33))> A< / div>< / div>


I am trying to scale a div, but keep the inside element at the same position and the same size. To do that, I use transform: scale(value) on wrapper and transform: scale(1/value) on the inside div.

The problem is, that the inside div shifts when I change scale. That only happens if width/height of wrapper is odd or not whole. It does not happen for even widths/height of the wrapper.

My goal is to have many child elements of wrapper that scale alongside wrapper, but only one that does not.

Take a look at this example to see problem in action (hover to scale).

Example with no issue, inner element stay fixed on scale (height and width of container are even):

https://jsfiddle.net/o16rau6u/5/

.wrapper {
  width: 200px;
  height: 200px;
  background-color: blue;
  position: relative;
}

.bg {
  width: 20px;
  height: 20px;
  display: inline-block;
  position: absolute;
  top: 50%;
  left: 50%;
  margin-top: -10px;
  margin-left: -10px;
  background-image: url("https://upload.wikimedia.org/wikipedia/commons/thumb/f/f9/Wiktionary_small.svg/350px-Wiktionary_small.svg.png");
  background-size: 100% 100%;
  background-repeat: no-repeat;
}

.wrapper:hover {
  transform: scale(2);
}

.wrapper:hover .bg {
  transform: scale(0.5);
}

<div id="wrapper" class="wrapper">
  <div id="bg" class="bg"></div>
</div>

Example with issue, the inner element move a little on scale (height and width of container are odd):

https://jsfiddle.net/o16rau6u/6/

.wrapper {
  width: 201px;
  height: 201px;
  background-color: blue;
  position: relative;
}

.bg {
  width: 20px;
  height: 20px;
  display: inline-block;
  position: absolute;
  top: 50%;
  left: 50%;
  margin-top: -10px;
  margin-left: -10px;
  background-image: url("https://upload.wikimedia.org/wikipedia/commons/thumb/f/f9/Wiktionary_small.svg/350px-Wiktionary_small.svg.png");
  background-size: 100% 100%;
  background-repeat: no-repeat;
}

.wrapper:hover {
  transform: scale(2);
}

.wrapper:hover .bg {
  transform: scale(0.5);
}

<div id="wrapper" class="wrapper">
  <div id="bg" class="bg"></div>
</div>

How can I fix this issue and avoid my elements to move on scale whataver the size of container is ?

PS : The example used above is a very simplified example to show the issue and it's not the needed output or the code used. So we are not looking for another way to achieve the same behavior above as it's pretty easy to be done.

解决方案

At the start I thought this is related to the calculation done by the browser and some rounding but it's seems to be bug. I have done a lot of test and whataver the value of the scale I use it always fail on odd value.

Here is a simple example with only scaleX

body:after {
  content: "";
  position: absolute;
  z-index: 999;
  top: 0;
  bottom: -200%;
  width: 2px;
  right: 50%;
  margin-right: -1px;
  background: rgba(0, 0, 0, 0.5);
}

.box {
  width: 200px;
  height: 100px;
  margin: 50px auto;
  background: blue;
  position: relative;
}

.inner {
  height: 20px;
  width: 20px;
  background: red;
  position: absolute;
  top: 50%;
  left: 50%;
  margin-left: -10px;
  text-align: center;
  color: #fff;
  margin-top: -10px;
}

<div class="box">
  <div class="inner">A</div>
</div>

<div class="box" style="transform:scaleX(2)">
  <div class="inner" style="transform:scaleX(0.5)">A</div>
</div>

<div class="box" style="width:201px;transform:scaleX(2)">
  <div class="inner" style="transform:scaleX(0.5)">A</div>
</div>

As you can see below, the browser seems to add an extra pixel to inner div, but if you look more closely the inner div has a correct size but it's being translated by 1px to the right. So the hover block of Dev Tools is positioned correctly but not element itself! So it seems that the browser correctly calculated the position but did a wrong painting.

The same issue appear if we simply apply scale on the container. So it's not because the scale of inner element:

body:after {
  content: "";
  position: absolute;
  z-index: 999;
  top: 0;
  bottom: -200%;
  width: 2px;
  right: 50%;
  margin-right: -1px;
  background: rgba(0, 0, 0, 0.5);
}

.box {
  width: 200px;
  height: 100px;
  margin: 50px auto;
  background: blue;
  position: relative;
}

.inner {
  height: 20px;
  width: 20px;
  background: red;
  position: absolute;
  top: 50%;
  left: 50%;
  margin-left: -10px;
  text-align: center;
  color: #fff;
  margin-top: -10px;
}

<div class="box" style="transform:scaleX(2)">
  <div class="inner">A</div>
</div>

<div class="box" style="width:201px;transform:scaleX(2)">
  <div class="inner">A</div>
</div>


Even if we use floating value with scale where we can say there is some rouding and complex calculation, we have correct output with even values and issue with odd values:

Example with scale(1.25) & scale(1/1.25):

body:after {
  content: "";
  position: absolute;
  z-index: 999;
  top: 0;
  bottom: -200%;
  width: 2px;
  right: 50%;
  margin-right: -1px;
  background: rgba(0, 0, 0, 0.5);
}

.box {
  width: 200px;
  height: 100px;
  margin: 50px auto;
  background: blue;
  position: relative;
}

.inner {
  height: 20px;
  width: 20px;
  background: red;
  position: absolute;
  top: 50%;
  left: 50%;
  margin-left: -10px;
  text-align: center;
  color: #fff;
  margin-top: -10px;
}

<div class="box">
  <div class="inner">A</div>
</div>

<div class="box" style="transform:scaleX(1.25)">
  <div class="inner" style="transform:scaleX(0.8)">A</div>
</div>

<div class="box" style="width:201px;transform:scaleX(1.25)">
  <div class="inner" style="transform:scaleX(0.8)">A</div>
</div>

Example with scale(1.33) & scale(1/1.33):

body:after {
  content: "";
  position: absolute;
  z-index: 999;
  top: 0;
  bottom: -200%;
  width: 2px;
  right: 50%;
  margin-right: -1px;
  background: rgba(0, 0, 0, 0.5);
}

.box {
  width: 200px;
  height: 100px;
  margin: 50px auto;
  background: blue;
  position: relative;
}

.inner {
  height: 20px;
  width: 20px;
  background: red;
  position: absolute;
  top: 50%;
  left: 50%;
  margin-left: -10px;
  text-align: center;
  color: #fff;
  margin-top: -10px;
}

<div class="box">
  <div class="inner">A</div>
</div>

<div class="box" style="transform:scaleX(1.33)">
  <div class="inner" style="transform:scaleX(calc(1 / 1.33))">A</div>
</div>

<div class="box" style="width:201px;transform:scaleX(1.33)">
  <div class="inner" style="transform:scaleX(calc(1 / 1.33))">A</div>
</div>

这篇关于对于奇数像素宽度,变换比例工作不正确的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆