Cross-browser fix - position: fixed as descendants of transformed elements - css

As described here and discussed in this chromium bug report according to W3C spec
In the HTML namespace, any value other than none for the transform results in the creation of both a stacking context and a containing block. The object acts as a containing block for fixed positioned descendants.
position: fixed that are descendant of any element with transform other than none are relative to that element.
However IE <= 11 and Firefox at least up to FF36 do not conform to the spec but position the element relative to the viewport (as originally intended).
Is there any fix ("polyfill") to get the same behaviour across all browsers?
Otherwise is there a way to "feature detect" instead of browser detect this behaviour to alternatively style affected elements?

I don't know of any "polyfills" to force cross browser consistency in this situation so, as it is presented as an acceptable alternative in the question, I'll provide an answer to the part about "feature detection".
You could test whether or not the browser complies with the spec by creating a couple of temporary elements, one nested inside the other. Use translatey() to move the parent element down from its "natural" position and fix the position of the child element, with a top value of 0. Then, by using getBoundingClientRect(), we can check whether or not the top of the child element is equal to that of the parent - if it is, the browser complies with the spec.
var body=document.body,
div=document.createElement("div"),
span=document.createElement("span"),
compliant;
div.style.transform="translatey(100px)";
span.style.position="fixed";
span.style.top=0;
div.appendChild(span);
body.appendChild(div);
compliant=span.getBoundingClientRect().top===div.getBoundingClientRect().top;
body.removeChild(div);
console.log(compliant);

Related

What's the difference between the ::after and ::backdrop pseudo-elements?

Well, what the title says.
I really couldn't find any detailed information on it, the MDN documentation is also rather sparse if not useless..
Can you possibly give examples and tips when one is preferred over the other?
(https://developer.mozilla.org/en-US/docs/Web/CSS/::backdrop)
This pseudo-element is a box rendered immediately below the element
(and above the element below the element in the stack, if any), within
the same top layer.
As you see in the documentation you mentioned, it will add a new element between your actual element and the element after.
With ::after you can insert content after the content of your selected element (so the content is still add to the same element), see this example.
Pseudo element after documentation:
Insert content before, or after, the content of an element
Over that, there is a difference in what browsers can render the pseudo elements: Backdrop vs. After. As you can see, today (2016-02-19) you can use ::backdrop only in chrome, opera and android browser.

What does it mean when Chrome Dev Tools shows a computed property greyed out

Please note, not the Styles panel (I know what greyed-out means in that context—not applied), but the next panel over, the Computed properties panel.
What does it mean when a Computed property is shown greyed out?
Example:
NB: This answer has no solid evidence, it's based on my observations along the time.
The gray calculated properties are neither default, nor inherited. This only occurs on properties that were not defined for the element, but calculated from either its children or parent based on runtime layout rendering.
Take this simple page as an example, display is default and font-size is inherited:
<style>
div { font-size: 13px; }
</style>
<div>
<p>asdf</p>
</div>
In this particular example, height is calculated from <p>'s children - text node (font size plus line height), width is calculated from its parent - <div>'s width, which is also calculated from its parent <body>.
EDIT: Well I thought again, here's my opinion based answer. I should really go and take a look at Chromium source code later :D
By expanding those arrows, you could see which actual rule is applied to the element, among all those defined against it (either directly or inherited, either by developer or browser):
Here you can trace down to every definition even including browser built-in rules, and check with the CSS cascading (overriding) mechanism.
So, for those elements that have no CSS definition (no directly defined, no inherited, no browser built-in), you don't have any source to trace. And the property values are totally runtime calculated.
If you check Show all, more grayed properties are shown. These are not defined anywhere either. But unlike those in previous screenshots, these are not runtime calculated - they are CSS spec default value.

Block element inside inline-block acting strangely in Firefox

Can anyone explain this behavior in FF?
Fiddle: http://jsfiddle.net/4mrt8wq3/
<style>
.b { display: inline-block; }
#a { display: block; }
</style>
<div class="b">
<label>xxxxxxxxxx</label>
<input type="text" id="a"/>
</div>
<div class="b">
<label>xxxxxxxxxx</label>
<div> / </div>
</div>
Only in firefox, the first div is positioned one line lower than the second. It works correctly in Chrome and IE (at least IE11). It's as if the block element within the inline-block is wrapping below the second element for some reason.
Using overflow: hidden on the first div fixes the problem, but the second div is then positioned slightly oddly with about 4 or 5 pixels of margin above it. Placing overflow-hidden on both causes it to render correctly.
I am not looking for a solution to the problem, as I've already found one, but I'm at a loss of explaining the behavior... Can anyone explain WHY it's doing this?
Yes, interesting question. First we need understand that the default vertical alignment of inline-block elements is baseline, and the baseline of each such element is the baseline of the last line box in them.
In the second div with class "b", the inner div itself contains a line box to hold the '/' character. That then provides the baseline for the second div with class "b".
That baseline must align level with the baseline of the first div with class "b". The question becomes: where is the baseline of the last line box in that div?
By making the input element itself display:block, Firefox¹ takes the view that the input element is "replaced", it's contents are opaque to CSS, therefore no line box is ever created by the input element. So the last line of the first div with class "b" is the one containing the label, and that is aligned level with the line of the '/' character.
Chrome takes a different view. Chrome treats the input element as having an internal structure visible to CSS, so the innards of the element form a line box, whose baseline then becomes the baseline of the first div with class "b", and it is that which aligned level with the '/' character.
When you add `overflow:hidden', it affects the baseline of the inline-blocks such that their baselines cease to be the baseline of their last contained line box, and becomes the bottom margin edge of the element.
Which behaviour is correct is unclear. It depends on history and the somewhat adulterated notion of replaced elements. In the early days of browsers, the rendering of some elements was delegated to external systems, either the underlying operating system or a plug-in. In particular, this was true of the input element, where rendering was done by O/S calls. The O/S had no notion of CSS, so rules had to be defined to allow the effectively black boxes to interact with the rest of the page. Such elements were classified as "replaced" elements.
Note the way this is defined. There is no official list of elements that are replaced elements, an element is a replaced element if the browser chooses to delegate its rendering to a system outside the CSS world, so in theory you could have two browsers, one delegating the rendering of an element and one natively rendering it, and from the CSS rules get quite different interactions.
As browsers progressed, they stopped delegating their rendering of the input element and rendered it themselves, in the process making the renderings CSS aware. This causes a problem because extant web pages, which assume that the input elements will be rendered using the replaced elements' rules, can become unusable. If a browser allowed that to happen, it would lose market share. So for the most part, to avoid this, the browsers implement those elements' layouts to interact with the page as if they were replaced elements, even though in reality they are not.
How far they go in this respect is not well specified. The HTML5 spec does not recognise the form controls as replaced elements, and suggests that they be rendered as inline-block, which would make Chrome's behaviour correct, but there are many ways in which all the browsers including Chrome simply don't behave that way. From a backward compatibility perspective with old web content, the Firefox behaviour is more reliable.
Until the layout of form controls is specified much more tightly than is the case currently, it is impossible to conclusively say which behaviour is correct.
¹For me, IE11 behaves like Firefox. Opera 28 (blink engine like Chrome) behaves like Chrome. Opera 12 (presto engine) behaves like Firefox.
Your problem is that per spec setting overflow:hidden changes the baseline position of an inline-block. Firefox implements what the spec says. Chrome does not.
Solution:
<style>
.b { display: inline-block;
vertical-align: top; /*add this line */
}
#a { display: block; }
</style>

Is there any HTML element that exists as the quintessential inline-block?

The div is the quintessential block level element, and the span is the inline counterpart. They are the simplest possible form of that display type, with no other properties. In a great many cases I will give either of them the style:
display: inline-block;
This makes them behave in a very handy way. For div it means boxes that will easily sit next to each-other, while maintaining their width and height as defined. For the span I can use this to make colorful rectangles. The inline-block display is great for so many things, but I have never seen an element that starts as an inline-block without anything else going on.
Images (img) are, but they are obviously not suited for the same things as a div, they have that style, but they fulfill a different purpose.
So is there an element that I don't know of that is the quintessential inline-block, or is this left out?
And if not, why? The uses of inline-block are numerous, so it seems like there should be some element that takes that basic form.
There's no such element, and there are some good reasons why not.
inline-block has several uses in contemporary web design. However it is not part of the original design, which only includes block and inline elements. Instead it derives from <img> as added by NSCA Mosaic. (Which uses the wrong markup and helped defeat the original "responsive design". I think we've only just started to fix the problems with img).
Further down the timeline, inline-block still wasn't part of IE4 or 5, or any version of Netscape. It wasn't part of the early HTML4 era. So we wouldn't expect to find your hypothetical element in that version of the standard. inline-block only appears in CSS2, which came after HTML4. (Look at the reference section in each standard).
Unlike block, inline-block is affected by whitespace in the markup. It's implied by the name, and it's what you'd expect from looking at <img> in the middle of some text (aka wordprocessor object anchored "as character"). But beyond its origins there, the whitespace-dependent markup soon becomes very troublesome. I wouldn't expect W3C HTML5 to enshrine this in a new element.
Specifying it would certainly involve argument about "semantics", separation of content and presentation etc. (As well as what to call it :). And if the default rendering makes whitespace significant - is that not part of the semantics of that element? Consider using images to represent words - or individual letters of a word (with appropriate alt text). This illustrates that the presence of whitespace (or not) around this element would be semantically significant, just like the presenceofwhitespaceseparatingwordsissemanticallysignificant. That seems like a big problem to me.
inline-block is often promoted as a modern alternative to using float everywhere. But neither is genuinely suitable. This is why CSS3 will standardize new layout modes: "flexbox" and "grid", to support modern responsive designs with genuine, clean markup. No dummy markup (or dummy generated content). No hacking around whitespace-dependence.
The only elements I can think of that have an in-line appearance, but allow for a width and height to be set, are:
img,
input,
textarea
select, and
button
The only element here, though, that can take HTML content is the button element; which is not an ideal use of the button since it's intended to be an element with which the user might/should interact; rather than simply a container element.
While you may have multiple uses for such an element, there's no convincing reason, given the ease with which the display property might be changed, that the W3C, or any other authority, should explicitly define one; especially given that the only difference between inline and inline-block is the ability to assign dimensions and margin.
The img tag is inline-block by default:
https://developer.mozilla.org/en-US/docs/Web/HTML/Element/Img
Edit: You can check this SO question: Is <img> element block level or inline level?

IE 6 & IE 7 Z-Index Problem

http://madisonlane.businesscatalyst.com
I'm trying to get the div#sign-post to sit above the div#bottom. This works fine in all browsers except IE6 & IE7. Can anyone see what the problem is here?
Also IE6 is displaying an additional 198px to the top of div#bottom.
Most of the answers here are wrong; some work, but not for the reason they state. Here is some explanation.
This is how z-index should work according to the spec:
you can give a z-index value to any element; if you don't, it defaults to auto
positioned elements (that is, elements with a position attribute different from the default static) with a z-index different from auto create a new stacking context. Stacking contexts are the "units" of overlapping; one stacking context is either completely above the another (that is, every element of the first is above any element of the second) or completely below it.
inside the same stacking context, the stack level of the elements is compared. Elements with an explicit z-index value have that value as a stack level, other elements inherit from their parents. The element with the higher stack level is displayed on top. When two elements have the same stack level, generally the one which is later in the DOM tree is painted on top. (More complicated rules apply if they have a different position attribute.)
In other words, when two elements have z-index set, in order to decide which will show on top, you need to check if they have any positioned parents which also have z-index set. If they don't, or the parents are common, the one with the higher z-index wins. If they do, you need to compare the parents, and the z-index of the children is irrelevant.
So the z-index decides how the element is placed compared to other children of its "stacking parent" (the closest ancestor with a z-index set and a position of relative, absolute or fixed), but it doesn't matter when comparing to other elements; it is the stacking parent's z-index (or possibly the z-index of the stacking parent's stacking parent, et cetera) which counts. In a typical document where you use z-index only on a few elements like dropdown menus and popups, none of which contains the other, the stacking parent of all the elements which have a z-index is the whole document, and you can usually get away with thinking of the z-index as a global, document-level ordering.
The fundamental difference with IE6/7 is that positioned elements start new stacking contexts, whether they have z-index set or not. Since the elements which you would instinctively assign z-index values to are typically absolutely positioned and have a relatively positioned parent or close ancestor, this will mean that your z-index-ed elements won't be compared at all, instead their positioned ancestors will - and since those have no z-index set, document order will prevail.
As a workaround, you need to find out which ancestors are actually compared, and assign some z-index to them to restore the order you want (which will usually be reverse document order). Usually this is done by javascript - for a dropdown menu, you can walk through the menu containers or parent menu items, and assign them a z-index of 1000, 999, 998 and so on. Another method: when a popup or dropdown menu becomes visible, find all its relatively positioned ancestors, and give them an on-top class which has a very high z-index; when it becomes invisible again, remove the classes.
Agree with validator comment - validating usually helps. But, if it doesn't heres a few pointers for z-index in IE:
1) elements who's z-index you're manipulating should be on the same level ie. you should be setting the z-index of #bottom and #body
if this is not feasible then
2) IE sometimes wont apply the z-index correctly unless the elements ou are applying it to have a position:relative. Try applying that property to #bottom and #body (or #signpost)
let me know how that works out
Darko
I just had this problem and the fix I found (thanks to Quirksmode) was to give the direct parent of the node you are trying to set a z-index of it's own z-index that is at less than the z-index of the node you are trying to set. Here is a quick example that should work in IE6
<html>
<head>
<style type="text/css">
#AlwaysOnTop {
background-color: red;
color: white;
width: 300px;
position: fixed;
top: 0;
z-index: 2;
}
#Header {
color: white;
width: 100%;
text-align: center;
z-index: 1;
}
</style>
</head>
<body>
<div id="Header">
<div id="AlwaysOnTop">This will always be on top</div>
</div>
<div id="Content">Some long amount of text to produce a scroll bar</div>
</body>
</html>
Welcome, I solved the problem with:
.header {
position: relative;
z-index: 1001;
}
.content {
position: relative;
z-index: 1000;
}
Looks to me like you have some malformed HTML in there. I tried counting, and perhaps I lost count of the opening and closing tags, but it looks like div#container isn't closed. Try running your page through a validator (such as W3C's HTML Validator, or something) and fixing some of the errors. That's helped me with these sorts of problems in the past. Good luck!
I've recently had an ongoing problem displaying one layer above another. In my case I was programmatically creating two layers in Javascript, one for diaplaying a custom control and one for creating a full screen layer behind it. FF was fine, bu IE displayed the full screen layer always on top of everything else.
After numerous trawls over the interweb, trying everyone's suggestions, the only way I eventually get it working was to remove position: attributes from both layers, and tweak the margin-top: attribute until I got a satisfactory result.
A bit of a hash, but it works and it'll be fine until IE 8 sorts out all of the current bugs......
the only reliable solution is, to put the top elements below in the code and then push them over the other stuff with absolute positioning.
e.g. Wordpress:
put the navigation in the footer file, but still inside the page wrapper.
might also bring some advantages for search engines, because they can directly start with the content, without crawling through the menu first...
UPDATE:
I need to correct myself. While putting the element below and then pushing it over is still the easiest way, there are certain cases when this is not possible in reasonable time. Then you have to make sure that each and every parent element has some kind of positioning and some senseful z-index. Then the z-index should work again even in IE7.

Resources