子 div 背景颜色在缩放时不能适应父 div。

7

根据浏览器的缩放级别,子div的背景颜色会出现奇怪的行为。会出现一些白色空格。

看这些例子:

缩放125%:

Zoom125

缩放150%:

Zoom150

缩放 175%:

Zoom175

缩放200%:

Zoom200

这是我的代码:

(JSFiddle链接:https://jsfiddle.net/3L4wfvyg/)

$(document).ready(function () {
    document.getElementById("HeaderContainer").addEventListener("click", function (e) {
        if (e.target.id != "FormContainer") {
            document.getElementById("Container3").classList.toggle("clicked");
            document.getElementById("HeaderContainer").classList.toggle("HeaderContainer3");
        };
    });
});
.Container1 {
  background-color: white;
  line-height: 30px;
  font-size: 20px;
  color: black;
  border: none;
  position: absolute;
}

.Container1 h3 {
  font-size: 30px;
  color: #142D41;
  margin-top: 20px;
  margin-bottom: 10px;
  position: relative;
}

.Container1 .Container3 {
  padding: 30px;
  display: block;
  border: 1px solid black;
  border-radius: 5px;
  margin-top: 15px;
  font-size: 15px;
  min-width: 100%;
  background-color: white;
  text-align: left;
  height: 100px;      
  overflow: hidden;
}
.Container1 .Container3:hover {
  text-decoration: none !important;
  cursor: pointer;
}            

.HeaderContainer3:hover {
  color: white !important;
  background-color: blue;
}

.HeaderContainer2 {
  padding: 30px;
}

.HeaderContainer1 {
  z-index: 10;
  position: relative;
  margin: -31px;
  padding: 32px 30px 25px 30px;
  width: auto;
}

.FormContainer {
  font-size: 20px !important;
}

#Container3 {
  height: 0px;
  transition: height 300ms ease-in-out;
  box-shadow: 0.1px 0.6px 2px 0px #8c8c8c;
}

#Container3.clicked {
  height: 314px;
}

.Header {
  position: relative;
  padding-top: 6px;
  overflow: hidden;
  width: 100%;
  height: 100%;
  cursor: auto;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
<div id="Container1" class="Container1">
  <h3>Title
  </h3>
  <div class="Container2">

    <div id="Container3" class="Container3">
      <div id="HeaderContainer" class="HeaderContainer1 HeaderContainer2 HeaderContainer3">
        <div class="Header">Header</div>
      </div>
      <div id="FormContainer" class="FormContainer">
        <hr />
        <div style="padding: 5px 0px 8px 0px;">
          Form
        </div>
        <br />
        <div id="FormElementsContainer" class="FormElementsContainer">
          <div>
            <b>First</b>
            <br />
          </div>
          <div>
            <b>Last</b>
            <br />
          </div>
          <div>
            <b>Third</b>
            <br />
          </div>
          <div>
            <br />
            <button>
              Submit
            </button>
          </div>
        </div>
        <br />
      </div>
    </div>
  </div>
</div>

为什么会发生这种情况,我该如何解决问题?
当我从Container3中删除边框时,似乎问题不再出现,但我不知道是否因为白色颜色使问题难以看到。

问题只出现在 JSFiddle 的输出上,还是浏览器的输出也有问题? - Roohullah Kazmi
你正在使用哪个浏览器以及它的版本号? - GucciBananaKing99
@RKazmi 这也是浏览器输出。 - Fth
@GucciBananaKing99 我已经在几个桌面浏览器上尝试过 - Chrome,Firefox和Safari。如果版本重要,我可以检查一下,但我没有发现任何浏览器不能重现这个问题,因此我不认为这是一个特定于浏览器的问题。 - Fth
我正在Ubuntu LTS上使用Firefox,我看不到这个问题。 - MrJami
请看下面我提出的修复方案,以及演示相同问题的精简版本。我还应该提到,您可能不需要一些样式。例如,在.Container1上设置默认的border: none,而div没有默认的border - Aaron Sarnat
4个回答

3

在高清/现代屏幕上,一个CSS像素不仅仅是一个屏幕像素,可能会导致缩放时出现一定的边缘效应。如果系统试图将多个屏幕像素映射到一个CSS像素,并被要求进行一些分数计算,有时候它会“丢失”一个屏幕像素。这就是为什么有时候会出现白色,以及在不同缩放级别下变化的原因。

对于提出问题的情况,也许做一个简单的hack,使父元素在悬停时具有蓝色背景,就足够了吗?

.Container1 .Container3:hover {
  text-decoration: none !important;
  cursor: pointer;
  background-color: blue;
  
}

谢谢您的解释。我尝试了您的建议,虽然它解决了问题,但是它会使整个元素(在单击后)变成蓝色,这不是我想要的。 - Fth
啊,我以为只是悬停并且到达父元素的边界。哪个元素不应该变成蓝色?这是点击还是悬停? - A Haworth
只有初始显示的方框在悬停时应变为蓝色。单击时,当方框被展开时,整个方框应具有白色背景颜色。实际上,这正是我示例代码中展示的确切行为。 :) - Fth

2

A Haworth 答案的启发:在处理不同缩放级别/屏幕密度时,将父元素着色确实更不容易出现渲染伪影。您可以从子元素中删除背景,并为父元素添加一个新的:hover选择器,仅在其不处于.clicked状态时激活。

.HeaderContainer3:hover {
  color: white !important;
  /** Background removed here **/
}

/** New block with a :not selector **/
.Container1 .Container3:hover:not(.clicked) {
  background-color: blue;
}   

Full working code example:

$(document).ready(function () {
    document.getElementById("HeaderContainer").addEventListener("click", function (e) {
        if (e.target.id != "FormContainer") {
            document.getElementById("Container3").classList.toggle("clicked");
            document.getElementById("HeaderContainer").classList.toggle("HeaderContainer3");
        };
    });
});
.Container1 {
  background-color: white;
  line-height: 30px;
  font-size: 20px;
  color: black;
  border: none;
  position: absolute;
}

.Container1 h3 {
  font-size: 30px;
  color: #142D41;
  margin-top: 20px;
  margin-bottom: 10px;
  position: relative;
}

.Container1 .Container3 {
  padding: 30px;
  display: block;
  border: 1px solid black;
  border-radius: 5px;
  margin-top: 15px;
  font-size: 15px;
  min-width: 100%;
  background-color: white;
  text-align: left;
  height: 100px;      
  overflow: hidden;
}
.Container1 .Container3:hover {
  text-decoration: none !important;
  cursor: pointer;
}

.Container1 .Container3:hover:not(.clicked) {
  background-color: blue;
}       

.HeaderContainer3:hover {
  color: white !important;
}

.HeaderContainer2 {
  padding: 30px;
}

.HeaderContainer1 {
  z-index: 10;
  position: relative;
  margin: -31px;
  padding: 32px 30px 25px 30px;
  width: auto;
}

.FormContainer {
  font-size: 20px !important;
}

#Container3 {
  height: 0px;
  transition: height 300ms ease-in-out;
  box-shadow: 0.1px 0.6px 2px 0px #8c8c8c;
}

#Container3.clicked {
  height: 314px;
}

.Header {
  position: relative;
  padding-top: 6px;
  overflow: hidden;
  width: 100%;
  height: 100%;
  cursor: auto;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
<div id="Container1" class="Container1">
  <h3>Title
  </h3>
  <div class="Container2">

    <div id="Container3" class="Container3">
      <div id="HeaderContainer" class="HeaderContainer1 HeaderContainer2 HeaderContainer3">
        <div class="Header">Header</div>
      </div>
      <div id="FormContainer" class="FormContainer">
        <hr />
        <div style="padding: 5px 0px 8px 0px;">
          Form
        </div>
        <br />
        <div id="FormElementsContainer" class="FormElementsContainer">
          <div>
            <b>First</b>
            <br />
          </div>
          <div>
            <b>Last</b>
            <br />
          </div>
          <div>
            <b>Third</b>
            <br />
          </div>
          <div>
            <br />
            <button>
              Submit
            </button>
          </div>
        </div>
        <br />
      </div>
    </div>
  </div>
</div>


谢谢。但是这会在第二次点击后使整个元素变成蓝色,这不是我想要的。请看我对A Haworth答案的评论。 - Fth

2

这里提供一个解决方案。它类似于其他人提出的建议,但考虑到了 .clicked 状态。

解决方法是在具有 borderborder-radius 属性的容器上设置 background-color 属性,而不是在嵌套容器上设置。它通过将 .HeaderContainer3:hover 选择器替换为 .Container3:not(.clicked):hover 来实现。

.Container3:not(.clicked):hover {
  color: white !important;
  background-color: blue;
}

可用的fiddle链接:https://jsfiddle.net/2eqLb6go/


至于为什么会出现这种情况,我没有技术上的答案,但它似乎与父容器具有border时嵌套容器的小数像素渲染有关。以下是一个简化形式的演示:

https://jsfiddle.net/0vje6k5w/

这似乎是由于使用border时的四舍五入误差导致的呈现问题。它似乎是根据不同的方式计算剪辑区域和边框宽度而导致不一致的透明像素间隙,可以将其舍入为01。带有border属性的容器的background被尊重(因此上述描述的修复方法有效),但是其中嵌套的任何内容都将被裁剪,并且似乎没有任何方法可以阻止发生这种情况。例如,即使子元素在其中绝对定位,问题仍然存在。

老实说,我认为这是关于页面缩放的框模型的错误实现。奇怪的是,所有主要浏览器在2021年都遭受了相同的行为。


刚刚注意到 @soimon 和我一样建议使用 .Container3:not(.clicked):hover,他比我早了一天 :P - Aaron Sarnat
谢谢。但是这会在第二次点击后使整个元素变成蓝色,这不是我想要的。请看我对A Haworth答案的评论。 - Fth

1

我把边框大小改为了0.0125em。(很奇怪,但有效!)

.Container1 .Container3 {                                           
   border: 0.0125em solid black;                                          
 }

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