Block element inside inline-block acting strangely in Firefox - css

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>

Related

Which CSS property is responsible for the difference in appearance between two elements with identical CSS settings?

The HTML below specifies a button and a div that have identical class and contents.
<div class="root"><!--
--><button class="outer"><div class="middle"><div class="inner">label</div></div></button><!--
--><div class="outer"><div class="middle"><div class="inner">label</div></div></div ><!--
--></div>
In this example, I have explicitly set every CSS property1 for the classes outer, middle, and inner2.
This means that both the button.outer and div.outer sub-trees of the DOM should have completely identical CSS settings. Presumably, as well, no CSS properties for these elements are getting their values from anywhere else besides the provided stylesheet.
As the example shows, the side-by-side button and div look quite different. Specifically, in the button, the label appears at the bottom of the element, whereas in the div it is vertically centered. (The label is centered horizontally in both cases. Also, note that all the classes have the setting vertical-align: middle.)
I have observed this difference with all the browsers I've tested so far (Chrome and Firefox).
Since there is no difference in the stylesheet settings for the button.outer and div.outer elements, and their descendants, I figure that the difference in their appearance is due to some CSS property with a value (such as auto or normal) that gets interpreted differently by the browser depending on the whether the context is a button or a div element.
My immediate goal here is to understand sufficiently well why the button and the div are being rendered differently so that I can adjust the CSS intelligently.
My longer term goal is to make CSS coding more predictable. Currently I find that my CSS is completely unstable due to gross inconsistencies like the one shown in the example.
My question is:
how can the difference in appearance between the button and the div be explained?
1 As reported by Chrome's devtool.
2 I took the vast majority of the values for these settings from Chrome's devtool's listings. The point was to ensure that both the button and the div elements had the same setting (whatever it may be) for each CSS property.
This is likely due to different meanings for the value of auto for the position of elements inside of a button. If you expand the size of a div, the content by default will be in the top-left corner. If you do the same for a button, the content will be centered horizontally and vertically.
Since the button's top and left values for auto is to be centered and not in the top left corner, you can reset top and left to always act like a typical div would. These are the properties to change on .middle:
.middle {
top: 0;
left: 0;
}
Here's the forked JSFiddle with those changes to .middle.
Different elements have different default settings. There is an enormous amount of CSS in your demos, and it's largely overkill and very hard to determine where exactly the differences in rendering are coming from.
Have you tried a CSS reset instead? These will resolve most of the discrepancies between elements and browsers, giving you a blank slate to add your own styles.
how can I determine the property (or properties) that account for the difference in appearance between the button and the div?
By clicking through them one by one and toggling them on and off in Dev Tools. If you turn off position:absolute on the middle class, you'll see what you're probably expecting in layout. I found this by clicking through all the properties in the Elements > Styles panel. See:
https://jsfiddle.net/vfdd9p8L/
This is probably a bug that you're encountering. Browsers have lots of them! By layering on so many styles at once, you're probably backing into a weird corner case with respect to the layout algorithms. To isolate the bug for help and/or reporting, try to create a reduced test case, which creates an unexpected discrepancy, but using the minimal number of elements and declarations.
(Also note that your fiddle is including jQuery CSS, which includes Normalize, which is a whole other layer of styling.)

Is there an opposite to display:none?

The opposite of visibility: hidden is visibility: visible. Similarly, is there any opposite for display: none?
Many people become confused figuring out how to show an element when it has display: none, since it's not as clear as using the visibility property.
I could just use visibility: hidden instead of display: none, but it does not give the same effect, so I am not going with it.
display: none doesn’t have a literal opposite like visibility:hidden does.
The visibility property decides whether an element is visible or not. It therefore has two states (visible and hidden), which are opposite to each other.
The display property, however, decides what layout rules an element will follow. There are several different kinds of rules for how elements will lay themselves out in CSS, so there are several different values (block, inline, inline-block etc — see the documentation for these values here ).
display:none removes an element from the page layout entirely, as if it wasn’t there.
All other values for display cause the element to be a part of the page, so in a sense they’re all opposite to display:none.
But there isn’t one value that’s the direct converse of display:none - just like there's no one hair style that's the opposite of "bald".
A true opposite to display: none there is not (yet).
But display: unset is very close and works in most cases.
From MDN (Mozilla Developer Network):
The unset CSS keyword is the combination of the initial and inherit keywords. Like these two other CSS-wide keywords, it can be applied to any CSS property, including the CSS shorthand all. This keyword resets the property to its inherited value if it inherits from its parent or to its initial value if not. In other words, it behaves like the inherit keyword in the first case and like the initial keyword in the second case.
(source: https://developer.mozilla.org/docs/Web/CSS/unset)
Note also that display: revert is currently being developed. See MDN for details.
When changing element's display in Javascript, in many cases a suitable option to 'undo' the result of element.style.display = "none" is element.style.display = "". This removes the display declaration from the style attribute, reverting the actual value of display property to the value set in the stylesheet for the document (to the browser default if not redefined elsewhere). But the more reliable approach is to have a class in CSS like
.invisible { display: none; }
and adding/removing this class name to/from element.className.
Like Paul explains there is no literal opposite of display: none in HTML as each element has a different default display and you can also change the display with a class or inline style etc.
However if you use something like jQuery, their show and hide functions behave as if there was an opposite of display none. When you hide, and then show an element again, it will display in exactly the same manner it did before it was hidden. They do this by storing the old value of the display property on hiding of the element so that when you show it again it will display in the same way it did before you hid it.
https://github.com/jquery/jquery/blob/740e190223d19a114d5373758127285d14d6b71e/src/css.js#L180
This means that if you set a div for example to display inline, or inline-block and you hide it and then show it again, it will once again show as display inline or inline-block same as it was before
<div style="display:inline" >hello</div>
<div style="display:inline-block">hello2</div>
<div style="display:table-cell" >hello3</div>
script:
$('a').click(function(){
$('div').toggle();
});
Notice that the display property of the div will remain constant even after it was hidden (display:none) and shown again.
you can use
display: normal;
It works as normal.... Its a small hacking in css ;)
I use
display:block;
It works for me
Here's an answer from the future… some 8 years after you asked the question. While there's still no opposite value for display: none, read on… There's something even better.
The display property is so overloaded it's not funny. It has at least three different functions. It controls the:
outer display type (how the element participates in the parent flow layout, e.g. block, inline)
inner display type (the layout of child elements, e.g. flex, grid)
display box (whether the element displays at all, e.g. contents, none).
This has been the reality for so long, we've learnt to live with it, but some long-overdue improvements are (hopefully!) coming our way.
Firefox now supports two-value syntax (or multi-keyword values) for the display property which separates outer and inner display types. For example, block now becomes block flow, and flex becomes block flex. It doesn't solve the problem of none, but the explicit separation of concerns is a step in the right direction I think.
Chromium (85+), meanwhile, has given us the content-visibility property, and announced it with some fanfare. It aims to solve a different problem—speeding up page load times by not rendering an element (and its child layouts) until it approaches the viewport and really needs to be seen, while still being accessible for 'Find' searches, etc. It does this automatically just by giving it the value auto. This is exciting news in itself, but look at what else it does…
The content-visibility: hidden property gives you all of the same
benefits of unrendered content and cached rendering state as
content-visibility: auto does off-screen. However, unlike with
auto, it does not automatically start to render on-screen.
This gives you more control, allowing you to hide an element's
contents and later unhide them quickly.
Compare it to other common ways of hiding element's contents:
display: none: hides the element and destroys its rendering state. This means unhiding the element is as expensive as rendering a new
element with the same contents.
visibility: hidden: hides the element and keeps its rendering state. This doesn't truly remove the element from the document, as it
(and it's subtree) still takes up geometric space on the page and can
still be clicked on. It also updates the rendering state any time it
is needed even when hidden.
content-visibility: hidden, on the other
hand, hides the element while preserving its rendering state, so, if
there are any changes that need to happen, they only happen when the
element is shown again (i.e. the content-visibility: hidden property
is removed).
Wow. So it's kind of what display: none should have been all along—a way of removing an element from the layout, gracefully, and completely independently of display type! So the 'opposite' of content-visibility: hidden is content-visibility: visible, but you have a third, very useful option in auto which does lazy rendering for you, speeding up your initial page loading.
The only bad news here is that Firefox and Safari are yet to adopt it. But who knows, by the time you (dear fellow developer) are reading this, that may have changed. Keep one eye on https://caniuse.com/css-content-visibility!
In the case of a printer friendly stylesheet, I use the following:
/* screen style */
.print_only { display: none; }
/* print stylesheet */
div.print_only { display: block; }
span.print_only { display: inline; }
.no_print { display: none; }
I used this when I needed to print a form containing values and the input fields were difficult to print. So I added the values wrapped in a span.print_only tag (div.print_only was used elsewhere) and then applied the .no_print class to the input fields. So on-screen you would see the input fields and when printed, only the values. If you wanted to get fancy you could use JS to update the values in the span tags when the fields were updated but that wasn't necessary in my case. Perhaps not the the most elegant solution but it worked for me!
I ran into this challenge when building an app where I wanted a table hidden for certain users but not for others.
Initially I set it up as display:none but then display:inline-block for those users who I wanted to see it but I experienced the formatting issues you might expect (columns consolidating or generally messy).
The way I worked around it was to show the table first and then do "display:none" for those users who I didn't want to see it. This way, it formatted normally but then disappeared as needed.
Bit of a lateral solution but might help someone!
You can use display: block
Example :
<!DOCTYPE html>
<html>
<body>
<p id="demo">Lorem Ipsum</p>
<button type="button"
onclick="document.getElementById('demo').style.display='none'">Click Me!</button>
<button type="button"
onclick="document.getElementById('demo').style.display='block'">Click Me!</button>
</body>
</html>
opposite of 'none' is 'flex' while working with react native.
To return to original state put:
display=""
Use display: revert
From the documentation stated on https://developer.mozilla.org/en-US/docs/Web/CSS/revert
The revert CSS keyword reverts the cascaded value of the property from its current value to the value the property would have had if no changes had been made by the current style origin to the current element. Thus, it resets the property to its inherited value if it inherits from its parent or to the default value established by the user agent's stylesheet (or by user styles, if any exist). It can be applied to any CSS property, including the CSS shorthand property all.
It supported accross all major browsers - https://caniuse.com/css-revert-value
visibility:hidden will hide the element but element is their with DOM. And in case of display:none it'll remove the element from the DOM.
So you have option for element to either hide or unhide. But once you delete it ( I mean display none) it has not clear opposite value. display have several values like display:block,display:inline, display:inline-block and many other. you can check it out from W3C.
display:unset sets it back to some initial setting, not to the previous "display" values
i just copied the previous display value (in my case display: flex;)
again(after display non), and it overtried the display:none successfuly
(i used display:none for hiding elements for mobile and small screens)
The best answer for display: none is
display:inline
or
display:normal
The best "opposite" would be to return it to the default value which is:
display: inline
You can use this display:block; and also add overflow:hidden;

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?

Clean CSS fix of IE7's 'float: right' drop bug

I continuously find myself having problems with elements floated right in IE7.
I have read many Stack Overflow questions which are similar to this one but there doesn't seem to be any consistently clean CSS answers.
What I mean by this is is I want to see answers which DO NOT change the HTML. E.g:
Put the floated element first
Add a 'clear: both' div after the floated element.
I understand that sometimes the floated element doesn't account for its parents height and therefore sometimes fails to contain it properly. Occasionally I find myself 'adding layout' to an element with zoom: 1 which sometimes fixes it. Other times I find myself messing about in a conditional IE7 style-sheet which isn't the best fix in my opinion.
Note: What I mean by 'having layout' - http://www.satzansatz.de/cssd/onhavinglayout.html
I have also read other answers to do with using relative and absolute positioning (parent div and child div respectively). This pulls it up but often affects surrounding divs.
I would be happy to add a bounty to this question if someone can give an in depth explain as to the reasons this happens and a detailed discussion of the various fixes, IDEALLY CSS ONLY!
Many thanks!
EDIT
The most common problem I encounter is when I have something like this:
Left Sidebar - Main - Right Sidebar
Right will often drop when floated. Ideally this should be in the format Left - Right - Main, but I continuously find myself styling developers work (Drupal mainly) where this is the case and it is too much hassle to get them to change their work. Make sense? Because I'm styling developers work they never put the clear block in too (which personally I think is horrible and dirty anyways!)
Introduction
Your title indicates a desire to see a fix for the float: right drop bug, but your text implies some broader scope desire to see solutions to “problems with elements floated right in IE7.” There are many general problems with floated elements (right or left) in that browser. Even though one may question whether support of the IE7 browser is worthy of much attention any more, it undoubtedly will remain so for some people for some time. Therefore, I’m going to take the opportunity here to address numerous issues at once regarding floats in that browser. Note that many experiments and references below come from an excellent resource: http://www.brunildo.org/test/index.html.
CSS for the Containing Element
For a containing parent to the floated element the following css should be set:
.container {
overflow: auto; /* forces clearing of the child float */
zoom: 1; /* give it layout (this can be some other css that does likewise) */
}
Making sure it hasLayout is important to prevent types of margin and padding errors, a type of peek-a-boo bug, and allowing the overflow to clear. For a sequence of floats, some html may need changing if padding on the container is desired to work properly.
With regards to one “drop” issue with a float: right, you may want to avoid setting an explicit height or max-height on the container. A min-height is okay. Setting a height and then having the float be taller than the container makes IE7 not behave with following elements. There is no pure css solution that I have found noted.
If the container is itself position: absolute there can be issues with positioning a float that may require that float itself to be set to position: absolute instead of being floated.
References:
For overflow to clear -- http://www.quirksmode.org/css/clearing.html
Margins -- http://www.brunildo.org/test/IEFloatAndMargins.html
Peek-a-boo -- http://www.brunildo.org/test/iew_boo.html and http://www.brunildo.org/test/iew_boo3.html
Float sequence padding -- http://www.brunildo.org/test/IEmfloa.html
Avoiding height -- http://austinmatzko.com/2007/07/25/internet-explorer-7-float-bug/, http://www.brunildo.org/test/fenc7.html (and his similar problem link on that page).
Container is absolute -- Floating Too Far Right!
CSS for the Floated Child
For a the floated child element, the css (besides float: right) to set depends on two things:
Absolute Container
Again, as noted above, a containing parent that is absolute may require a change in how the child is handled.
Float is Also a Clearing Element
If the float is also going to have a clear set on it, then there are numerous issues that can arise depending totally upon the html and css of the elements around it. There is no single canonical fix, so look at the references below.
References:
Container is absolute -- Floating Too Far Right!
Also having clear -- http://www.brunildo.org/test/IEWfc.html, http://www.brunildo.org/test/IEWfc2.html, http://www.brunildo.org/test/IEWfc3.html
CSS for Child Elements of Container Before the Float
If the float: right follows an element in the html structure that should be to its left (and not above it), then that preceding element(s) must be float: left.
CSS for Child Elements of Container After the Float
A Clear Element
For an element after the float that has clear set, then if it has padding and background-color, make sure it also hasLayout to avoid a doubling of the padding; also this prevents extra space above the clear due to container padding, and avoids other margin issues.
References:
For padding -- http://www.brunildo.org/test/IEClearPadding.html and http://www.brunildo.org/test/IEFloatClearPadding.html
For margins -- http://www.brunildo.org/test/Op7_margins_float.html (look down the page for IE7)
A Paragraph Before a Clear Element
Having a paragraph with a margin-bottom and shorter in height than the float, located between the floated element and a clearing element, can create an extra gap between the clear and the float equal to that margin. There is no known pure css fix other than giving the paragraph a zero bottom margin (which may not be acceptable if the paragraph may go taller than the float).
Reference:
Paragraph following -- http://www.brunildo.org/test/IEFloatClearMargin.html
Conclusion
I cannot guarantee I have addressed every issue that may occur with a right floated object, but certainly many major ones are covered. As to “why” these things happen, it is all “bugginess` in IE7.
Have you tried to use the clearfix solution to collapsing divs? There are variations on this and there is a newer version but I don't have the url to hand, but this is standard clearfix css which you add to the parent element that is collapsing and causing issues with floated elements http://www.webtoolkit.info/css-clearfix.html. Chris Coyer has a better version here http://css-tricks.com/snippets/css/clear-fix/.
You say "I understand that sometimes the floated element doesn't account for its parents height and therefore sometimes fails to contain it properly" this is kind of true, the parent will collapse if all child elements are floated. This is due to the elements being removed from the normal flow, when this occurs the parent div is unable to calculate its height and collapses as if there isn't anything inside of the div.
But without seeing the page and the issue you are having I can only estimate that the issue is due to IE6-IE7's haslayout property which is really annoying, they sorted it out from version 8 upwards but it does add extra development time to your build.
But in most situations the clearfix solution is best as it doesn't add extra markup to the page such as
<div style="clear: both"></div>
this is old and out of date and should be avoided.
I hope this helps you, if you need any more information or I have not answered the question just ask.
We have been using the clearfix solution for years now.
.cf:after { content: "."; display: block; clear: both; visibility: hidden; line-height: 0; height: 0; }
.cf { display: inline-block; }
html[xmlns] .cf { display: block; }
* html .cf { height: 1%; }
This is a simple CSS class which, ideally, has to be applied to a container that has any child float elements. Since you're restrictive about not changing the HTML at all, you can either:
replace all occurrences of .cf with your own div's selector [or]
use JS to apply the class (which is bad because users will see a broken layout a few seconds until the page loads completely) [or]
use PHP ob_start() + regex to apply the class [or]
just go vintage and rewrite everything using tables (as we used to do in the `90s)
It's simple:
Where you have float:right, add *clear:left.
Or where you have float:left, add *clear:right.
* for IE7-
Or for validation
*+html .class{clear:left/right}
I know it's been a year since this was posted, but I found a solution that I like for this. The gist is using 'expression' tag in your CSS for IE7 only to move the floated element to be the first element of the parent in the DOM. It will be semantically correct for all other browsers, but for IE7 we modify the DOM to move the floated element.
In my case, I have:
<div>
<h1></h1>...<p>any other content...</p>
<small class="pull-right"></small>
</div>
In my CSS for pull-right, I use:
.pull-right {
float:right;
*zoom: ~"expression( this.runtimeStyle.zoom='1',parentNode.insertBefore( this,parentNode.firstChild ))";
}
The result is that IE7 moves my <small> to be the first element of <div> but all other browsers leave the markup alone.
This might not work for everyone. Technically, it is modifying the markup but only in the DOM for IE7 and it's also a javascript solution.
Also, I understand there may be some performance issues with expression (it's slow), so perhaps it's not ideal there are a lot of floats like this. In my case, it worked well and allowed me to keep semantically correct HTML.

What is the difference between visibility:hidden and display:none?

The CSS rules visibility:hidden and display:none both result in the element not being visible. Are these synonyms?
display:none means that the tag in question will not appear on the page at all (although you can still interact with it through the dom). There will be no space allocated for it between the other tags.
visibility:hidden means that unlike display:none, the tag is not visible, but space is allocated for it on the page. The tag is rendered, it just isn't seen on the page.
For example:
test | <span style="[style-tag-value]">Appropriate style in this tag</span> | test
Replacing [style-tag-value] with display:none results in:
test | | test
Replacing [style-tag-value] with visibility:hidden results in:
test |                        | test
They are not synonyms.
display:none removes the element from the normal flow of the page, allowing other elements to fill in.
visibility:hidden leaves the element in the normal flow of the page such that is still occupies space.
Imagine you are in line for a ride at an amusement park and someone in the line gets so rowdy that security plucks them from the line. Everyone in line will then move forward one position to fill the now empty slot. This is like display:none.
Contrast this with the similar situation, but that someone in front of you puts on an invisibility cloak. While viewing the line, it will look like there is an empty space, but people can't really fill that empty looking space because someone is still there. This is like visibility:hidden.
One thing worth adding, though it wasn't asked, is that there is a third option of making the object completely transparent. Consider:
1st unseen link.<br />
2nd unseen link.<br />
3rd unseen link.
(Be sure to click "Run code snippet" button above to see the result.)
The difference between 1 and 2 has already been pointed out (namely, 2 still takes up space). However, there is a difference between 2 and 3: in case 3, the mouse will still switch to the hand when hovering over the link, and the user can still click on the link, and Javascript events will still fire on the link. This is usually not the behavior you want (but maybe sometimes it is?).
Another difference is if you select the text, then copy/paste as plain text, you get the following:
1st link.
2nd link.
3rd unseen link.
In case 3 the text does get copied. Maybe this would be useful for some type of watermarking, or if you wanted to hide a copyright notice that would show up if a carelessly user copy/pasted your content?
display:none removes the element from the layout flow.
visibility:hidden hides it but leaves the space.
There is a big difference when it comes to child nodes. For example: If you have a parent div and a nested child div. So if you write like this:
<div id="parent" style="display:none;">
<div id="child" style="display:block;"></div>
</div>
In this case none of the divs will be visible. But if you write like this:
<div id="parent" style="visibility:hidden;">
<div id="child" style="visibility:visible;"></div>
</div>
Then the child div will be visible whereas the parent div will not be shown.
They're not synonyms - display: none removes the element from the flow of the page, and rest of the page flows as if it weren't there.
visibility: hidden hides the element from view but not the page flow, leaving space for it on the page.
display: none removes the element from the page entirely, and the page is built as though the element were not there at all.
Visibility: hidden leaves the space in the document flow even though you can no longer see it.
This may or may not make a big difference depending on what you are doing.
With visibility:hidden the object still takes up vertical height on the page. With display:none it is completely removed. If you have text beneath an image and you do display:none, that text will shift up to fill the space where the image was. If you do visibility:hidden the text will remain in the same location.
display:none will hide the element and collapse the space is was taking up, whereas visibility:hidden will hide the element and preserve the elements space. display:none also effects some of the properties available from javascript in older versions of IE and Safari.
visibility:hidden preserves the space; display:none doesn't.
In addition to all other answers, there's an important difference for IE8: If you use display:none and try to get the element's width or height, IE8 returns 0 (while other browsers will return the actual sizes). IE8 returns correct width or height only for visibility:hidden.
display: none;
It will not be available on the page and does not occupy any space.
visibility: hidden;
it hides an element, but it will still take up the same space as before. The element will be hidden, but still, affect the layout.
visibility: hidden preserve the space, whereas display: none doesn't preserve the space.
Display None Example:https://www.w3schools.com/css/tryit.asp?filename=trycss_display_none
Visibility Hidden Example : https://www.w3schools.com/cssref/tryit.asp?filename=trycss_visibility
visibility:hidden will keep the element in the page and occupies that space but does not show to the user.
display:none will not be available in the page and does not occupy any space.
display: none
It will remove the element from the normal flow of the page, allowing other elements to fill in.
An element will not appear on the page at all but we can still interact with it through the DOM.
There will be no space allocated for it between the other elements.
visibility: hidden
It will leave the element in the normal flow of the page such that is still occupies space.
An element is not visible and Element’s space is allocated for it on the page.
Some other ways to hide elements
Use z-index
#element {
z-index: -11111;
}
Move an element off the page
#element {
position: absolute;
top: -9999em;
left: -9999em;
}
Interesting information about visibility: hidden and display: none properties
visibility: hidden and display: none will be equally performant since they both re-trigger layout, paint and composite. However, opacity: 0 is functionality equivalent to visibility: hidden and does not re-trigger the layout step.
And CSS-transition property is also important thing that we need to take care. Because toggling from visibility: hidden to visibility: visible allow for CSS-transitions to be use, whereas toggling from display: none to display: block does not. visibility: hidden has the additional benefit of not capturing JavaScript events, whereas opacity: 0 captures events
If visibility property set to "hidden", the browser will still take space on the page for the content even though it's invisible.
But when we set an object to "display:none", the browser does not allocate space on the page for its content.
Example:
<div style="display:none">
Content not display on screen and even space not taken.
</div>
<div style="visibility:hidden">
Content not display on screen but it will take space on screen.
</div>
View details
There are a lot of detailed answers here, but I thought I should add this to address accessibility since there are implications.
display: none; and visibility: hidden; may not be read by all screen reader software. Keep in mind what visually-impaired users will experience.
The question also asks about synonyms. text-indent: -9999px; is one other that is roughly equivalent. The important difference with text-indent is that it will often be read by screen readers. It can be a bit of a bad experience as users can still tab to the link.
For accessibility, what I see used today is a combination of styles to hide an element while being visible to screen readers.
{
clip: rect(1px, 1px, 1px, 1px);
clip-path: inset(50%);
height: 1px;
width: 1px;
margin: -1px;
overflow: hidden;
padding: 0;
position: absolute;
}
A great practice is to create a "Skip to content" link to the anchor of the main body of content. Visually-impaired users probably don't want to listen to your full navigation tree on every single page. Make the link visually hidden. Users can just hit tab to access the link.
For more on accessibility and hidden content, see:
https://webaim.org/techniques/css/invisiblecontent/
https://webaim.org/techniques/skipnav/
Summarizing all the other answers:
visibility
display
element with visibility: hidden, is hidden for all practical purposes (mouse pointers, keyboard focus, screenreaders), but still occupies space in the rendered markup
element with display:none, is hidden for all practical purposes (mouse pointers, keyboard focus, screenreaders), and DOES NOT occupy space in the rendered markup
css transitions can be applied for visibility changes
css transitions can not be applied on display changes
you can make a parent visibility:hidden but a child with visibility: visible would still be shown
when parent is display:none, children can't override and make themselves visible
part of the DOM tree (so you can still target it with DOM queries)
part of the DOM tree (so you can still target it with DOM queries)
part of the render tree
NOT part of the render tree
any reflow / layout in the parent element or child elements, would possibly trigger a reflow in these elements as well, as they are part of the render tree.
any reflow / layout in the parent element, would not impact these elements, as these are not part of the render tree
toggling between visibility: hidden and visible, would possibly not trigger a reflow / layout. (According to this comment it does: What is the difference between visibility:hidden and display:none? and possibly according to this as well https://developers.google.com/speed/docs/insights/browser-reflow)
toggling between display:none to display: (something else), would lead to a layout /reflow as this element would now become part of the render tree
you can measure the element through DOM methods
you can not measure the element or its descendants using DOM methods
If you have a huge number of elements using visibility: none on the page, the browser might hang while rendering, as all these elements require layout, even though they are not shown
If you have a huge number of elements using display:none, they wouldn't impact the rendering as they are not part of the render tree
Resources:
https://developers.google.com/speed/docs/insights/browser-reflow
http://www.stubbornella.org/content/2009/03/27/reflows-repaints-css-performance-making-your-javascript-slow/
Performance differences between visibility:hidden and display:none
Other Info:
There are some browser support idiosyncrancies as well, but they seem to apply to very old browsers, and are available in the other answers, so I have not discussed them here.
There are some other alternatives to hide element, like opacity, or absolute positioning off screen. All of them have been touched upon in some or the other answers, and have some drawbacks.
According to this comment (Performance differences between visibility:hidden and display:none), if you have a lot of elements using display:none and you change to display: (something else), it will cause a single reflow, while if you have multiple visibility: hidden elements and you turn them visible, it will cause reflow for each element. (I don't really understand this)
One other difference is that visibility:hidden works in really, really old browsers, and display:none does not:
https://www.w3schools.com/cssref/pr_class_visibility.asp
https://www.w3schools.com/cssref/pr_class_display.asp
The difference goes beyond style and is reflected in how the elements behave when manipulated with JavaScript.
Effects and side effects of display: none:
the target element is taken out of the document flow (doesn't affect layout of other elements);
all descendants are affected (are not displayed either and cannot “snap out” of this inheritance);
measurements cannot be made for the target element nor for its descendants – they are not rendered at all, thus their clientWidth, clientHeight, offsetWidth, offsetHeight, scrollWidth, scrollHeight, getBoundingClientRect(), getComputedStyle(), all return 0s.
Effects and side-effects of visibility: hidden:
the target element is hidden from view, but is not taken out of the flow and affects layout, occupying its normal space;
innerText (but not innerHTML) of the target element and descendants returns empty string.
As described elsewhere in this stack, the two are not synonymous. visibility:hidden will leave space on the page whereas display:none will hide the element entirely. I think it's important to talk about how this affects the children of a given element. If you were to use visibility:hidden then you could show the children of that element with the right styling. But with display:none you hide the children regardless of whether you use display: block | flex | inline | grid | inline-block or not.
display:none; will neither display the element nor will it allot space for the element on the page whereas visibility:hidden; will not display the element on the page but will allot space on the page.
We can access the element in DOM in both cases.
To understand it in a better way please look at the following code:
display:none vs visibility:hidden

Resources