位置:固定在位置:固定:哪个浏览器正确? [英] Position:fixed within position:fixed: which browser is correct?

查看:70
本文介绍了位置:固定在位置:固定:哪个浏览器正确?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在Chrome / Safari和Firefox中,将固定元素放置在另一个固定元素中的行为有所不同。


此答案很好地解释了相对位置内的固定div和 rel = nofollow noreferrer> MDN很清楚


固定位置不要为元素。而是将其定位在相对于屏幕视口的指定位置,并且在滚动时不要移动它。打印时,将其放置在每个页面上的该固定位置。


我不明白的是Firefox在固定的div中使用固定的div做什么div。我期望的是子元素在悬停时随包装一起移动。


  .wrapper, .header {
position:fixed;
宽度:320px;
}

.wrapper:hover {
left:0px;
}
.wrapper {
width:320px;
身高:100%;
背景:白色;
溢出:滚动;
还剩:-200px;
过渡:所有缓和0.3s;
}
ul {
margin-top:120px;
}
.header {
background:rgba(255,255,255,0.9);
}

body {
背景:灰色;

 < div class = wrapper> 
< div class = header>
Lorem ipsum dolor坐在amet,私服精英人士。 Repudiandae vitaa,itaque commodi,odio等。 Excepturi,过时了吗? Architect repellendus omnis mollitia animi rem准在,驱除阿波罗vol虫ati虫耳垢!
< / div>
< ul>
< li>
Lorem ipsum dolor坐在amet,私服精英人士。 Accusantium quam maiores,Voluptas facere,iste quis iusto reiciendis delectus,quad blanditiis tempora。 Earum voluptatum dicta quae,在Rerum假定的说明!
< / li>
< li>
Lorem ipsum dolor坐在amet,私服精英人士。 Accusantium quam maiores,Voluptas facere,iste quis iusto reiciendis delectus,quad blanditiis tempora。 Earum voluptatum dicta quae,在Rerum假定的说明!
< / li>
< li>
Lorem ipsum dolor坐在amet,私服精英人士。 Accusantium quam maiores,Voluptas facere,iste quis iusto reiciendis delectus,quad blanditiis tempora。 Earum voluptatum dicta quae,在Rerum假定的说明!
< / li>
< li>
Lorem ipsum dolor坐在amet,私服精英人士。 Accusantium quam maiores,Voluptas facere,iste quis iusto reiciendis delectus,quad blanditiis tempora。 Earum voluptatum dicta quae,在Rerum假定的说明!
< / li>
< / ul>
< / div>


有什么想法吗?我也在寻找一种变通方法,以在所有浏览器之间保持一致。


编辑:更有趣吗?


添加此操作可以进一步解决FF:

  .header:hover {
height:200px;
}

悬停时,它将触发重新绘制,然后FF重新计算元素的位置。


使用FF 46.0.1,Chrome 54.0.2840.71和Safari版本9.1.1(11601.6.17)进行的测试。 注意:我已经阅读了此问题

解决方案

要查看所需行为的两种解决方法,请向下滚动至水平线以下。




11/18/16更新-CSSWG回到我身边,说应该创建一个新的堆栈上下文:


< blockquote>

你是对的,这是还应该合并到定位规范中-现在已体现出来。谢谢。






哪个浏览器是正确的主题:


已固定位置元素应始终相对于视口放置 ,具体来说,建立 = a。= https://www.w3.org/TR/CSS22/visudet.html# contains-block的 position:fixed 元素的包含块-details rel = nofollow noreferrer>在1​​0.1.3中的通过视口


如果元素的位置为:固定,则包含块由视口[...]


建立。此包含块被正式称为初始包含块。 / p>

9.3.1 还表示,对于普通的非分页媒体(如此类),


[...]对于掌上电脑,投影,屏幕,tty和电视媒体类型,此框相对于视口是固定的,并且在滚动时不会移动。


代码中发生的事情是,您正在更改悬停时父元素的 left 属性的值,并且您希望子元素也会移动。但是,子元素不会(正确地)移动。


10.3.7


为了计算静态位置,包含以下内容的块固定位置的元素是初始包含块,而不是视口。


(此处的静态位置是指元素在正常流中的位置)。


它还说:


[如果] left和 right分别是 auto和legco.gov.hk legco.gov.hk width不是 auto,请将 left设置为静态位置,否则将 right设置为静态位置。然后求解 left(如果 direction为 rtl)或 right(如果 direction为 ltr)。


此相信,我解释了为什么子元素 position:fixed 最初设置为 left:-200px; 的原因如果位于位置,则将在其父元素内:静态


此时,您似乎认为父级的新<我假设code> left 值应该移动子元素,因为您希望新的 left 属性将被继承子(不是的工作方式),或者您希望它对文档进行重排,这在<$上不会发生我记得c $ c>:hover 浏览器仅在:hover 上进行重新绘制,这不会更改文档流,但会更改元素的外观(例如背景色不透明度可见度:隐藏; 等)。


因此,除非有伪选择器在临时状态下更改属性(例如:hover

在这种情况下,Chrome和Safari似乎在执行规范要求之外的其他操作;它们要么导致完全重排,要么设置了位置:固定元素以继承祖先的 left 属性。根据 CSS工作组草案由下面的Oriol链接。但是,在更新规范之前,这仍然是非标准行为。



  • 长话短说,Chrome和Safari现在错误 ,但最终一旦规范更新,它们将是正确的,Firefox将不得不更新其渲染行为。




使 .header div继承新的 left 属性,因为这就是Chrome的工作方式,这就是您寻求的行为。我还稍微调整了 .header 的宽度,以使其不会覆盖 .wrapper :


  .wrapper,.header {
位置:已固定;
}

.wrapper:hover {
left:0px;
}
.wrapper {
width:320px;
身高:100%;
背景:白色;
溢出:滚动;
还剩:-200px;
过渡:所有缓和0.3s;
}
ul {
margin-top:120px;
}
.header {
background:rgba(255,255,255,0.9);还剩
:继承;
宽度:303像素;
}

body {
背景:灰色;
}

 < div class = wrapper > 
< div class = header>
Lorem ipsum dolor坐在amet,私服精英人士。 Repudiandae vitaa,itaque commodi,odio等。 Excepturi,过时了吗? Architect repellendus omnis mollitia animi rem准在,驱除阿波罗vol虫ati虫耳垢!
< / div>
< ul>
< li>
Lorem ipsum dolor坐在amet,私服精英人士。 Accusantium quam maiores,Voluptas facere,iste quis iusto reiciendis delectus,quad blanditiis tempora。 Earum voluptatum dicta quae,在Rerum假定的说明!
< / li>
< li>
Lorem ipsum dolor坐在amet,私服精英人士。 Accusantium quam maiores,Voluptas facere,iste quis iusto reiciendis delectus,quad blanditiis tempora。 Earum voluptatum dicta quae,在Rerum假定的说明!
< / li>
< li>
Lorem ipsum dolor坐在amet,私服精英人士。 Accusantium quam maiores,Voluptas facere,iste quis iusto reiciendis delectus,quad blanditiis tempora。 Earum voluptatum dicta quae,在Rerum假定的说明!
< / li>
< li>
Lorem ipsum dolor坐在amet,私服精英人士。 Accusantium quam maiores,Voluptas facere,iste quis iusto reiciendis delectus,quad blanditiis tempora。 Earum voluptatum dicta quae,在Rerum假定的说明!
< / li>
< / ul>
< / div>


Positioning a fixed element inside another fixed element is behaving differently in Chrome / Safari vs Firefox.

This answer explains well the expected behavior for a fixed div inside a relative one, and MDN is pretty clear on this:

Fixed Positioning Do not leave space for the element. Instead, position it at a specified position relative to the screen's viewport and don't move it when scrolled. When printing, position it at that fixed position on every page.

What I don't understand is what Firefox is doing with a fixed div inside a fixed div. What I expect is that the child element moves along with the wrapper on hover.

.wrapper, .header {
  position:fixed;
  width:320px;
}

.wrapper:hover{
  left:0px;
}
.wrapper{
  width:320px;
  height:100%;
  background:white;
  overflow:scroll;
  left:-200px;
  transition: all ease-out .3s;
}
ul {
  margin-top:120px;
}
 .header {
   background:rgba(255,255,255,0.9);
}

body{
  background:gray;

<div class="wrapper">
  <div class="header">
    Lorem ipsum dolor sit amet, consectetur adipisicing elit. Repudiandae vitae a, itaque commodi, odio et. Excepturi, obcaecati? Architecto repellendus omnis mollitia animi rem quasi at, odit aperiam voluptatibus voluptates earum!
  </div>
  <ul>
    <li>
      Lorem ipsum dolor sit amet, consectetur adipisicing elit. Accusantium quam maiores, voluptas facere, iste quis iusto reiciendis delectus, quod blanditiis tempora. Earum voluptatum dicta quae, explicabo placeat at rerum assumenda!
    </li>
    <li>
      Lorem ipsum dolor sit amet, consectetur adipisicing elit. Accusantium quam maiores, voluptas facere, iste quis iusto reiciendis delectus, quod blanditiis tempora. Earum voluptatum dicta quae, explicabo placeat at rerum assumenda!
    </li>
    <li>
      Lorem ipsum dolor sit amet, consectetur adipisicing elit. Accusantium quam maiores, voluptas facere, iste quis iusto reiciendis delectus, quod blanditiis tempora. Earum voluptatum dicta quae, explicabo placeat at rerum assumenda!
    </li>
    <li>
      Lorem ipsum dolor sit amet, consectetur adipisicing elit. Accusantium quam maiores, voluptas facere, iste quis iusto reiciendis delectus, quod blanditiis tempora. Earum voluptatum dicta quae, explicabo placeat at rerum assumenda!
    </li>
  </ul>
</div>

Any thoughts? I'm looking for a workaround to have consistency across browsers, too.

Edit : more fun?

Add this to glitch it even more on FF :

.header:hover{
  height:200px;
}

On hover, it triggers a repaint, then FF recalculate the position of the element.

Tests made with FF 46.0.1, Chrome 54.0.2840.71 and Safari Version 9.1.1 (11601.6.17). Note: I already read this question

解决方案

To see two workarounds for the behavior you want, scroll down below the horizontal rule.


11/18/16 Update - The CSSWG got back to me and said that it should create a new stacking context:

You're right, this was supposed to be merged into the positioning spec as well - reflected now. Thanks.


On the subject of which browser is correct:

fixed position elements should always be placed relative to the viewport, specifically that the position: fixed element's containing block is established "by the viewport" in 10.1.3:

If the element has 'position: fixed', the containing block is established by the viewport [...]

This containing block is formally called the "initial containing block".

9.3.1 also backs this up by saying that, for normal non-paged media (like this),

[...] In the case of handheld, projection, screen, tty, and tv media types, the box is fixed with respect to the viewport and does not move when scrolled.

What's happening in your code is that you are changing the value of the left property of the parent element on hover, and you are expecting the child element to move, too. However, the child element is (properly) not moving.

10.3.7 says

For the purposes of calculating the static position, the containing block of fixed positioned elements is the initial containing block instead of the viewport.

(static position here meaning the position of the element if it were placed in the normal flow).

It also says:

[If] 'left' and 'right' are 'auto' and 'width' is not 'auto', [...] set 'left' to the static position, otherwise set 'right' to the static position. Then solve for 'left' (if 'direction is 'rtl') or 'right' (if 'direction' is 'ltr').

This explains, I believe, why the child position: fixed element is initially set to left: -200px; per where it would be within its parent element if it were position: static.

At this point, it looks like you believe the parent's new left value should move the child element, I'm assuming, either because you expect the new left property to be inherited by the child (which is not how left works), or you expect it to re-flow the document, which doesn't happen on :hover as I recall; the browser only re-paints on :hover, which doesn't change the document flow, but does change the appearance of elements (e.g. background-color, opacity, visibility: hidden; etc).

So... elements on re-paint shouldn't move unless there are pseudo-selectors that change the properties during temporary states (like :hover), or transitions/animations at play.

In this situation, it appears that Chrome and Safari are doing something other than what the spec suggests; they are either causing a full re-flow, or they have set position: fixed elements to inherit left properties from ancestors. This appears to be above the board, if you will, according to the CSS Working Group draft linked by Oriol below. However, it's still non-standard behavior until the spec is updated.

  • Long-story short, Chrome and Safari are wrong right now, but eventually once the spec is updated, they will be correct, and Firefox will have to update its rendering behavior.

Make the .header div inherit your new left property, since that's how Chrome is doing it and that is the behavior you seek. I also adjusted .header's width just a bit, so that it won't cover the scroll bar on .wrapper:

.wrapper, .header {
  position: fixed;
}

.wrapper:hover {
  left:0px;
}
.wrapper{
  width:320px;
  height:100%;
  background:white;
  overflow:scroll;
  left:-200px;
  transition: all ease-out .3s;
}
ul {
  margin-top:120px;
}
.header {
  background:rgba(255,255,255,0.9);
  left: inherit;
  width: 303px;
}

body{
  background:gray;
}

<div class="wrapper">
  <div class="header">
    Lorem ipsum dolor sit amet, consectetur adipisicing elit. Repudiandae vitae a, itaque commodi, odio et. Excepturi, obcaecati? Architecto repellendus omnis mollitia animi rem quasi at, odit aperiam voluptatibus voluptates earum!
  </div>
  <ul>
    <li>
      Lorem ipsum dolor sit amet, consectetur adipisicing elit. Accusantium quam maiores, voluptas facere, iste quis iusto reiciendis delectus, quod blanditiis tempora. Earum voluptatum dicta quae, explicabo placeat at rerum assumenda!
    </li>
    <li>
      Lorem ipsum dolor sit amet, consectetur adipisicing elit. Accusantium quam maiores, voluptas facere, iste quis iusto reiciendis delectus, quod blanditiis tempora. Earum voluptatum dicta quae, explicabo placeat at rerum assumenda!
    </li>
    <li>
      Lorem ipsum dolor sit amet, consectetur adipisicing elit. Accusantium quam maiores, voluptas facere, iste quis iusto reiciendis delectus, quod blanditiis tempora. Earum voluptatum dicta quae, explicabo placeat at rerum assumenda!
    </li>
    <li>
      Lorem ipsum dolor sit amet, consectetur adipisicing elit. Accusantium quam maiores, voluptas facere, iste quis iusto reiciendis delectus, quod blanditiis tempora. Earum voluptatum dicta quae, explicabo placeat at rerum assumenda!
    </li>
  </ul>
</div>

这篇关于位置:固定在位置:固定:哪个浏览器正确?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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