box-sizing not inherited through DETAILS element? - html

Using a common technique for inheriting box-sizing, the value is not inherited by the child elements of the DETAILS element even though the DETAILS element has the proper value.
In the example snippet, the DIV outside the DETAILS element inherits box-sizing--as expected and desired--but the DIV inside the DETAILS element does not. You can verify with DevTools.
Firefox and Chrome both exhibit this behavior. Is the behavior correct?
*, *::after, *::before { box-sizing: inherit; }
html { box-sizing: border-box; }
<div>Box sizing outside Details?</div>
<details open>
<summary>Summary</summary>
<div>Box sizing inside Details?</div>
</details>

Generally, it's pretty safe to say that if Chrome and Firefox exhibit the same surprising behaviour, then it's correct.
And this is no different. The HTML5 standard says:
The details element is expected to render as a block box. The element is also expected to have an internal shadow tree with two slots. ...
The details element's second slot is expected to have its style attribute set to "display: block; content-visibility: hidden;" when the details element does not have an open attribute. When it does have the open attribute, the style attribute is expected to be removed from the second slot.
Because the slots are hidden inside a shadow tree, this style attribute is not directly visible to author code. Its impacts, however, are visible.
So the slots are effectively elements with style, and the child elements of the details element inherit that style, not the style of the details element. And because *, *::after, *::before won't match the slot, what the div inherits is the initial value of box-sizing, which is content-box.

This seems to be a known issue, where the box-sizing property is not properly inherited by child elements inside a details element. According to some sources, this is due to a bug in some browser rendering engines. To resolve this, you can add the following code to explicitly set the box-sizing property for elements inside the details element:
details div {
box-sizing: inherit;
}
<div>Box sizing outside Details?</div>
<details open>
<summary>Summary</summary>
<div>Box sizing inside Details?</div>
</details>

Related

How to overrlay a gradient over an image [duplicate]

Given the following scenario, why does the :after selector require a content property to function?
.test {
width: 20px;
height: 20px;
background: blue;
position:relative;
}
.test:after {
width: 20px;
height: 20px;
background: red;
display: block;
position: absolute;
top: 0px;
left: 20px;
}
<div class="test"></div>
Notice how you do not see the pseudo element until you specify the content property:
.test {
width: 20px;
height: 20px;
background: blue;
position:relative;
}
.test:after {
width: 20px;
height: 20px;
background: red;
display: block;
position: absolute;
top: 0px;
left: 20px;
content:"hi";
}
<div class="test"></div>
Why is this the intended functionality? You would think that the display block would force the element to show up. Oddly enough, you can actually see the styles inside web debuggers; however, they do not display on the page.
Here are some references to various W3C specifications and drafts:
Selectors Level 3
The :before and :after pseudo-elements can be used to insert generated content before or after an element's content.
The :before and :after pseudo-elements
Authors specify the style and location of generated content with the :before and :after pseudo-elements. As their names indicate, the :before and :after pseudo-elements specify the location of content before and after an element's document tree content. The content property, in conjunction with these pseudo-elements, specifies what is inserted.
The content attribute
Initial: none
This property is used with the :before and :after pseudo-elements to generate content in a document. Values have the following meanings:
none - The pseudo-element is not generated.
The styling applied to ::before and ::after pseudo-elements affects the display of the generated content. The content attribute is this generated content, and without it present, the default value of content: none is assumed, meaning there is nothing for the style to be applied to.
If you don't want to repeat content:''; multiple times, you can override this simply by globally styling all ::before and ::after pseudo-elements within your CSS (JSFiddle example):
::before, ::after {
content:'';
}
The reason you need a content: '' declaration for each ::before and/or ::after pseudo-element is because the initial value of content is normal, which computes to none on the ::before and ::after pseudo-elements. See the spec.
The reason the initial value of content isn't an empty string but a value that computes to none for the ::before and ::after pseudo-elements, is twofold:
Having empty inline content at the start and end of every element is rather silly. Remember that the original purpose of the ::before and ::after pseudo-elements is to insert generated content before and after the main content of an originating element. When there's no content to insert, creating an additional box just to insert nothing is pointless. So the none value is there to tell the browser not to bother with creating an additional box.
The practice of using empty ::before and ::after pseudo-elements to create additional boxes for the sole purpose of layout aesthetics is relatively new, and some purists might even go so far as to call it a hack for this reason.
Having empty inline content at the start and end of every element means that every (non-replaced) element — including html and body — would by default generate not one box, but up to three boxes (and more in the case of elements that already generate more than just the principal box, like elements with list styles). How many of the two extra boxes per element will you actually use? That's potentially tripling the cost of layout for very little gain.
Realistically, even in this decade, less than 10% of the elements on a page will ever need ::before and ::after pseudo-elements for layout.
And so these pseudo-elements are made opt-in — because making them opt-out is not only a waste of system resources, but just plain illogical given their original purpose. The performance reason is also why I do not recommend generating pseudo-elements for every element using ::before, ::after.
But then you might ask: why not have the display property default to none on ::before, ::after? Simple: because the initial value of display is not none; it is inline. Having inline compute to none on ::before, ::after is not an option because then you could never display them inline. Having the initial value of display be none on ::before, ::after is not an option because a property can only have one initial value. (This is why the initial value of content is always normal and it is simply defined to compute to none on ::before, ::after.)
Based on your comments on others' answers, I believe your question is actually:
Why must the content property for pseudo-classes be set in the CSS, as
opposed to the content of non-pseudo-classes, which may be set in
either HTML or CSS?
The reason is that:
by definition, pseudo-classes are dynamically created for every single element specified by a page's HTML markup
all page elements, including pseudo-classes, must have a content property to be displayed.
HTML elements like <p> do as well, but you can set their content property quickly using markup (or with CSS declarations).
Howver, unlike non-pseudo-class-elements, pseudo-classes cannot be given values in the markup itself.
∴ Therefore, all pseudo-classes are invisible (their 'content' properties have no value) unless you tell them not to be (by giving them value with CSS declarations).
Take this simple page:
<body>
<p> </p>
</body>
We know this page will display nothing, because the <p> element has no text. A more accurate way to rephrase this, is that the <p> element's content property has no value.
We can easily change this, by setting the content property of the h1 element in the HTML markup:
<body>
<p>This sentence is the content of the p element.</p>
</body>
This will now display when loaded, because the content property of the <p> element has a value; that value is a string:
"This sentence is the content of the p element."
Alternatively, we can cause the <p> element to be displayed by setting the content property of the <p> element in the CSS:
p { content: "This sentence is the content of the p element set in the CSS."; }
These two ways of injecting the string into the <p> element are identical.
Now, consider doing the same thing with pseudo-classes:
HTML:
<body>
<p class="text-placeholder">P</p>
</body>
CSS:
p:before { content: "BEFORE... " ; }
p:after { content: " ...and AFTER"; }
The result:
BEFORE... P ...and AFTER
Finally, imagine how you would accomplish this example without using CSS. It's impossible, because there is no way to set the content of the pseudo-class in the HTML markup.
You might be creative and imagine something like this might work:
<p:before>BEFORE... </p>
<p> P </p>
<p:after> ...and AFTER</p>
But, it doesn't, because <p:before> and <p:after> are not HTML elements.
In conclusion:
Pseudo classes exist for every markup element.
They are invisible by default, because they are initialized with no content property.
You CANNOT set the content property for pseudo classes with HTML markup.
∴ Therefore, pseudo-elements' content property must be declared with CSS declarations, in order to be displayed.
Until you add content: ..., the psuedo-element doesn't actually exist.
Setting other style properties is not enough to force the browser to create the element.
2020 Edit
:before
Is syntax from CSS2 for better practices you should write the newest syntax from CSS3 which is
::before
with double semicolons
Full answer and differences can be found here:
What is the difference between :before and ::before?

<legend> tag accepts width if inline

When I apply the following styling to a legend tag
display: inline;
width: 300px;
I see that the legend tag has a width of 300px It still accepts the width. Here is a demo. Is there something special with this element, because I expect inline elements to ignore the width setting!
This may be a case similar to button elements, as described in Bindings:
10.5.2 - The button element
#namespace url(http://www.w3.org/1999/xhtml);
button { binding: button; }
When the button binding applies to a button element, the
element is expected to render as an 'inline-block' box rendered as a
button whose contents are the contents of the element.
Chrome seems to do the same for legend elements.
But probably it shouldn't be doing that, because
The spec doesn't define such binding for legend elements.
legend elements shouldn't be replaced elements (they are listed in the Non-replaced elements section), so they should conform to CSS rules.

How to prevent inheritance of any css style of parent node to child node?

Assume a body node having a child node (e.g. div).
There may be css styles attached to the body, which are not known in advance (they are specific to an arbitrary page accessible on the WWW).
The child node (e.g. div) has a bunch of css styles which are static.
How to prevent css styles of the parent to "influence" styling of the child?
There is no generic way. You need to set a value (other than inherit) for every property that has inherit as the default value.
Even that won't prevent all influence.
e.g.
body { width: 300px; }
div { width: auto; }
The width of the div is influenced by the width of the body.
You could use values initial (compatibility: not supported by IE at all) and unset (Fx27+ only)
The initial CSS keyword applies the initial value of a property to an element. It is allowed on every CSS property and causes the element for which it is specified to use the initial value of the property.
where initial value means:
The initial value given in the summary of the definition of each CSS property has different meaning for inherited and non-inherited properties.
For inherited properties, the initial value is used, for the root element only, when no value is specified for the element.
For non-inherited properties the initial value is used, for any element, when no value is specified for the element.
Source for links and quotes: MDN
Relevant polyfill: https://stackoverflow.com/a/15903168/137626 (brace yourself)
You could reset all properties to desired defaults in the child div like this.
div *{
property1:default;
....
propertyx:deafult;
}

Should global css styles be set on the html element or the body element?

Sometimes I see people apply global css styles to html, sometimes I see them apply them to body, with both raw css and javascript.
Are there any differences between the two? Which is the standard to make a global css style? Is there anything I should know when picking between them?
I'm assuming that "global page styling" here refers to things such as fonts, colors and backgrounds.
Personally, I apply global page styling, for the most part, to body and the simple element selectors (p, h1, h2, h3..., input, img, etc). These elements are more closely related to the presentation of content of an HTML page to the user.
My rationale for this is simple: the presentational attributes bgcolor, background, text, topmargin, leftmargin and others were given to the body element, not the html element. These attributes are now converted to their respective CSS rules with extremely low precedence in the cascade:
The UA may choose to honor presentational attributes in an HTML source document. If so, these attributes are translated to the corresponding CSS rules with specificity equal to 0, and are treated as if they were inserted at the start of the author style sheet.
Most if not all implementations I'm aware of will convert these to CSS rules on body, based on their HTML equivalents. Others such as link, alink and vlink will become a:link, a:active and a:visited rules respectively.
Of course, it should be noted that CSS itself doesn't really have any semantics to it per se, as it's a styling language in itself which is completely separate from the content structure of an HTML document. Although the introduction to CSS2.1 covers the basics of styling an HTML document, note that the section calls itself non-normative (or informative); this means it doesn't set any hard and fast rules for CSS implementers to follow. Instead, it simply provides information for readers.
That said, certain styles may be applied to html to modify viewport behavior. For example, to hide the page scrollbars use:
html {
overflow: hidden;
}
You can also apply rules to both html and body for interesting effects; see the following questions for details and examples:
What's the difference in applying CSS to html, body, and *?
Applying a background to <html> and/or <body>
Note that html is not the viewport; the viewport establishes an initial containing block in which html is situated. That initial containing block cannot be targeted with CSS, because in HTML, the root element is html.
Note also that, technically, there is no difference between applying properties to html and body that are inherited by default, such as font-family and color.
Last but not least, here is an excellent article that details the differences between html and body in terms of CSS. In summary (quoted from its first section):
The html and body elements are distinct block-level entities, in a
parent/child relationship.
The html element's height and width are controlled by the browser window.
It is the html element which has (by default) overflow:auto, causing
scrollbars to appear when needed.
The body element is (by default) position:static, which means that
positioned children of it are
positioned relative to the html
element's coordinate system.
In almost all modern browsers, the built-in offset from the edge of the
page is applied through a margin on
the body element, not padding on the
html element.
As the root element, html is more closely associated with the browser viewport than body (which is why it says html has overflow: auto for scrollbars). Note however that the scrollbars are not necessarily generated by the html element itself. By default, it's the viewport that generates these scrollbars; the values of overflow are simply transferred (or propagated) between body, html, and the viewport, depending on which values you set. The details of all this are covered in the CSS2.1 spec, which says:
UAs must apply the 'overflow' property set on the root element to the viewport. When the root element is an HTML "HTML" element or an XHTML "html" element, and that element has an HTML "BODY" element or an XHTML "body" element as a child, user agents must instead apply the 'overflow' property from the first such child element to the viewport, if the value on the root element is 'visible'. The 'visible' value when used for the viewport must be interpreted as 'auto'. The element from which the value is propagated must have a used value for 'overflow' of 'visible'.
The last bullet point probably has its roots in the aforementioned topmargin and leftmargin attributes of the body element.
If you want to style only the content that'll be displayed, targeting the <body> element saves the style rules an unnecessary level of cascading.
Is there a reason you'd want to apply styles to the <title>, <meta>, <script> etc... tags? That would happen by targeting <html>.

What CSS properties can be applied to which HTML elements

I'm looking for a source/spec that can tell me what CSS properties can applied to which HTML elements. For instance, the css property; "overflow". I know I can apply this to div, p, textarea but what other elements can I apply this too? Is there a spec somewhere I can reference?
See http://www.w3.org/TR/CSS2/ and http://www.w3.org/TR/CSS/.
For example, regarding your question about the overflow property, see:
http://www.w3.org/TR/CSS2/visufx.html#overflow-clipping, stating:
'overflow'
Value: visible | hidden | scroll | auto | inherit
Initial: visible
Applies to: block-level and replaced elements
Inherited: no
Percentages: N/A
Media: visual
In the CSS processing model, every element has every property that is applicable to the target media type. For example, even the empty <br> element has the color property. But whether a property has an effect on the rendering of the element itself depends on the specific property and the context, in a manner that is described in applicable CSS specifications and drafts. It is usually described under an “Applies to” heading. There is no combined compilation of this, and the set of properties recognized by browsers varies considerably.
Even though a property “applies to” an element by the specifications, it need not have an actual effect. For example, border-color is irrelevant for the rendering of an element if its border-style is none or its border-width is 0. (The value may still matter if it is inherited by child elements.)
Any CSS property can be applied to any HTML element; they don't restrict each other.
However, as Aron Rotteveel mentioned, the element will have to be either a replaced element (like img), or specified to be block-level. That mean that the following is perfectly fine CSS:
strong { display: block; height: 5em; width: 5em; overflow: scroll; }
You could always use the official spec. The answer to your particular question is here.