How to cope with chrome/firefox margin-collapsing <details>/<summary> differently? - html

Gaze upon this example HTML/CSS, and observe how Chrome (v110) and Firefox (v108) render them differently.
* {border:0; margin:0; padding:0; vertical-align:baseline;}
details {margin:0;}
details summary {margin: 1em 0 1em 1em;}
<details>
<summary>First</summary>
</details>
<details>
<summary>Second</summary>
</details>
The first <details> tag is notably empty except for its <summary>.
As best I can figure, Chrome is deciding to margin collapse the bottom margin of the first <summary> with the top margin of the second <summary> only when the <details> is open, whereas Firefox collapses them in either case. I'm building a semantic "template", so I'd like to know how to write the CSS to be Firefox/Chrome agnostic. I want:
The opening/closing of <details> that are empty except for their <summary> to not affect the spacing/margins at all.
Consistent margins between open, empty <details> and closed <details>.
How do you write CSS that will render the HTML consistently?
Researching this browser discrepancy, it appears Firefox is the one out of compliance with the W3 standards. See this potentially related CSS margin test. Collected potentially relevant reading here:
SO: Do vertical margins collapse reliably and consistently across all browsers?
SO: Cross-browser Issue: Min-height and collapsing margins
SO: Firefox body margin bug?
Chromium "Issue" 321295

Differences in Firefox/Chrome aside, there's a way to avoid this issue altogether.
Declare no margins in <summary>; instead put them in <details>.
details {margin: 1em 0 1em 1em;}
details summary {margin:0;}
This makes sense, because <details> is the "block" element here, and should be handling the margins relative to any other block elements in your HTML. The <summary> tag has default value display:list-item;—it's really just intended to contain some text or something to click to expand the details.

Related

HTML: <code> heightens block box - any remedies to get it back in vertical rhythm?

I'm currently getting my block- and inline-elements into a vertical rhythm (baseline pattern).
Most of my inline-elements do well and stay in their inline box, bowing themselves to my line-height. Most do so, but a little village of stubborn Gauls - called the <code>-tag.
I let jquery tell me padding (0), margin (0), border (0) and line-height (as expected) - all seems right (whereupon padding, margin and border shouldn't have any effect on the baseline of an inline element anyways). But unfortunately: The code tag extends my technical inline box (block container), why the following lines of text are translated down one or a few pixels.
<code>
some code
</code>
Writing this question, it appears that stackoverflow itself got this problem managed, as some code isn't disrupting the baseline. Stackoverflow uses e.g. css: p code {padding: 1px 5px;}, but it even works here when I disable this or other styles, why I can't derive a solution for my problem.
Anyone an explanation or any elixir to normalize the <code> Gaul? p.s.: It's not on my normalize.css - got no preformatting for this tag yet. Applying the preformats of Bootstrap (Gallagher) doesn't solve this either. My doctype is <!DOCTYPE html>.
Solution found: Set your css standardize/normalize to ...
code
{
line-height:normal;
}
The kbd and samp tags need this too. Although the line-height was inherited correctly before (and had the same height as other elements), code, kbd and samp seemed to be shifted somehow. The above setting makes them stay in baseline (Problem appeared in Firefox 35.0). Setting line-height to zero works too... whyever.

div with inline-block children doesn't display consistently with identical CSS

I have a div that contains several inline-block children:
The DOM looks like this:
It has the following CSS:
Each child has the following css:
If one unchecks and rechecks the display: block line marked above in the Chrome debugger, the div now looks like this:
Note that there is now space between the labels, and they are more readable. However, the CSS used to render this is presumably identical. Moreover, the div is actually still display: block when the specific selector's display: block is unchecked; it just obtains this from a less specific selector (in my case, the UA stylesheet for div).
I want the div to render the second way - is there a way to make this happen? How is the div supposed to be rendered, and where does the spacing between the display: inline-block elements come from?
UPDATE: This is probably caused by a weird interaction between Chrome's renderer and Meteor's Blaze rendering engine, and won't be seen except on highly dynamic pages.
This is a result of whitespace being evaluated. You can throw:
font-size: 0;
on the parent div and this will go away. Alternatively, adjust your markup to remove space between the list items.

What HTML elements might have browser set default padding/margin?

I know that ol and ul elements have default padding set on almost all browsers. Apparently h{#} tags do too on some browsers.
How do I get a list of all elements?
I could simply do * { margin: 0; padding: 0; } (which is my desired result), but that's simply bad.
The W3C has a (informative, not normative) default stylesheet for HTML 4 here:
http://www.w3.org/TR/CSS2/sample.html
where you can see that no elements have padding, but body, h1..h6, p, fieldset, form, ul, ol, dl, dir, menu, blockquote and dd have a margin by default.
This is a somewhat solved problem. You have two options:
A 'reset' stylesheet, one that removes all special styling (like padding and margin) from (almost all) elements, so you can start 'fresh'. You'll need to redefine things like font-weight for <b>old and <strong>. Reset.css is a popular choice.
A stylesheet that sets sensible defaults. This would, for example, remove paddings and margins, but then add them again so that browsers are consistent with each other. The stylesheet included in the HTML5 Boilerplate can be stripped or used as-is for your purposes.
You can also use the above two stylesheets as a guide on what elements might have margins and paddings in different user agents and roll your own. In my opinion, setting sensible defaults (the second option) is better, since you might forget things like :focus styles with a plain 'reset stylesheet'.
You can use a simple CSS reset, a list of all resets: http://perishablepress.com/press/2007/10/23/a-killer-collection-of-global-css-reset-styles/
And you can get a look into a Useragent Stylesheet: http://meiert.com/en/blog/20070922/user-agent-style-sheets/
But there are very much elements with padding/margin:
body
blockquote
dd
p
ect.

Styling the `<html>` element in CSS?

Can anyone explain to me why can we style the element html?
What are differences between it and body?
I usually see tutorials and multiple websites using body and never html, I only found about it when using YUI 3: CSS Reset since changing the background in body didn't work.
Edit: Actually, I still haven't found the problem regarding that, when I add the reset.css the background gets white, when I remove it returns to normal. Yet Chrome inspector says that the background is the normal one. Btw, this is getting off topic. :p
Edit 2: The culprit was the doctype. Somehow it made the html style in the css-reset render after the body style in my stylesheet. Maybe I should open a question regarding this.
Doctype: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
Quite often you'll find people styling the HTML element since it does have an affect on the way the page is rendered.
The most notable style you're likely to see is
html,body{
min-height:101%;
}
This is used to ensure that the scroll bars in browsers like Firefox, always show on the page. This stops the page shifting left and right when changing between long and short pages.
The reason we're allowed to style the html element is because it is a DOM element like any other. All DOM elements can be styled to be something they are not, like a container. Take this example:
<html><body>This is my page.</body></html>
Using CSS to limit the body to 80% width, setting borders on the body and giving the html a different background color (creating an "off page" effect) would be perfectly acceptable, keeping the semantics of the markup intact without resorting to div clutter.
Here's a technique I discovered for centering containers (vertically and horizontally) on the screen without using tons of divs or tables, or even having to know the size of the centered container.
html {
display:table;
width:100%;
height:100%;
}
body {
display:table-cell;
vertical-align:middle;
}
body > div {
# "shrink wraps" the div so you don't have to specify a width.
# there's probably a better way to do precisely that, but this works.
display:table;
margin:0 auto; # center the div
}
You can style the html element (heck you can head, title { display: block; } if you like), but browser support is a bit weak (IIRC, Internet Explorer <8 has issues).
Offhand, I would say: <html> is not a visible element per se, and it contains sections for semantic (e.g. <head>) and presentation data (<body>).
On the other hand, <body> is a block for visible elements, so it can be given a presentation style.
But people do apply styles to the <html> element for a couple cases: (a) because all of its child elements will inherit that style, and (b) in special cases like the scrollbar trick that Jamie Dixon mentioned.
I don't believe you can, but styling <body> should work for you
html is the containing element for the whole document, it contains the <body> which is what is rendered by the browser and <head> which contains meta information on the page/document you are viewing. It has actually no use to be able to style the html element since it isn't rendered by the browser.
It can however be used to build you css selectors with (html div.dataView { color: red } for example)

Remove padding for an empty element

I'm generating a page for an upcoming portal site, and I've got an HTML element with some optional content. I'd like the element to not render if it is empty, but adding some padding to it causes it to render. How do I add padding to the content, but only if content is present?
.someElement{padding-top: 5px;}
HTML in question:
<div class="someElement">With padded content</div>
<div class="someElement"><!-- shouldn't render since it has no content --></div>
Basically, I'd like the second element, above, to not take up any space. I'm testing in all major browsers, using XHTML 1.1 doctype.
You can do the trick with the CSS3 pseudo-class :empty
.someElement
{
// your standard style
}
.someElement:empty
{
display:none;
}
Sadly Internet explorer doesn't support that feauture yet. For all the other browsers it shall do just fine...
Give the element an id attribute. You can then use Javascript to check it's innerHTML property once the page has loaded. If innerHTML has a length of zero, then you can set it's display property to none. This page might help if you don't know your javascript.
This is still a mucky way to play. If you know the element shouldn't be rendered before you serve the page it would be better to omit it altogether. If you don't want to omit the element, just hide it, then force it into hiding; style="display: none"
<style>
.someElement{padding-top: 5px; display:table;}
</style>
<div class="someElement">With padded content</div>
<div class="someElement"><!-- shouldn't render since it has no content --></div>
Adding display:table; should do the trick.
Give the empty element a different class (say someHiddenElement) when you are generating the content. Then add someHiddenElement { display: none } to your style sheet.
If it's necessary to have the div.someElement in the HTML, the best CSS/HTML way to do that would be to add an extra div around the added content that has the padding property
.someElement > div{padding-top:5px;}
<div class="someElement"><div>Content</div></div>
Otherwise, do as Pekka says, or take a look at having javascript do it for you.
I can't think of a CSS only way to do that.
I would try to decide whether the element is rendered at the time I know whether there will be any content in it. That is probably the cleanest solution.
Don't use padding on container, use margin on content. Than when there is no content, container remains invisible.
At the point where you populate the optional div, if there is no text to put in it, try changing the CSS display property to none. According to this source (and others), display: none removes the element completely from the document. It does not take up any space, even though the HTML for it is still in the source code.