Google Chrome seems to have a bug when overflowing content inside of a fieldset.
Here is a jsfiddle that demonstrates the problem: http://jsfiddle.net/Dismissile/Lnm42/
If you look at the page, you will see that when you have a container inside of a fieldset, and the container has overflow: auto set, and that container has content that will overflow horizontally, the fieldset actually expands instead of using a scrollbar:
<fieldset class="parent">
<div class="child">
<div class="grandchild">
asdf
</div>
</div>
</fieldset>
<div class="parent">
<div class="child">
<div class="grandchild">
asdf
</div>
</div>
</div>
CSS:
.parent {
border: 1px solid green;
padding: 20px;
margin: 20px;
}
.child {
border: 1px solid red;
padding: 20px;
overflow: auto;
}
.grandchild {
border: 1px solid #ccc;
width: 2000px;
padding: 10px;
}
Is there a CSS hack/fix I can use so that content overflows properly when inside a fieldset in Chrome?
UPDATE:
As of a recent Chrome for MS Windows update (v28 maybe? Haven't tracked it down yet), auto is no longer a valid value for min-width, and this solution no longer works!
New solution:
Using inherit instead of auto appears to fix the issue for all cases I have tested so far. (Including the original fiddle.. see the new fiddle fix for details.)
The updated fix: FIELDSET {min-width: inherit; }
Original answer:
Chrome defines for fieldset the default user agent style: min-width: -webkit-min-content.
So when your viewable area (aka "screen") is smaller than your div with specific width, the -webkit-min-content grows the fieldset to accommodate the size of the contents (plus padding, etc.).
The fix: FIELDSET { min-width: auto; }
I fixed your fiddle, try it out!
Using a pseudo fieldset (aka <div class="fieldset"></div>) I believe you can get close. See jsfiddle.
Try this styling:
fieldset,.fieldset {
margin: 10px;
border: solid 1px black;
position: relative;
padding: .5em;
}
.legend {
left: 0.5em;
top: -0.6em;
color: black;
position: absolute;
background-color: white;
padding: 0 0.25em 0 0.25em;
}
It is less than ideal as fieldset styling needs to be duplicated, but for me it was the only tolerable solution to my run-in with this problem that I have been able to come up with. As above you may be able to apply your existing fieldset styling to the pseudo one.
Try:
fieldset {
display: table-cell;
min-width: 0;
box-sizing: border-box;
}
This is your example with fix: http://jsfiddle.net/2u3a9goc/
Using JavaScript to set the width of the viewport:
http://jsfiddle.net/Lnm42/2/
I added a class called fieldset-width to the fieldset:
<fieldset class="parent fieldset-width">
Then added this JQuery code:
$(document).ready(function() {
$(".fieldset-width").css("width", $(window).width() - 82);
});
$(window).resize(function() {
$(".fieldset-width").css("width", $(window).width() - 82);
});
My only comment is that I can't think of a good reason to interfere with the default fieldset functionality. I dislike "scroll bars within scroll bars" to begin with. For input fields, which fieldsets usually surround, I would be especially cautious about making the user scroll around to get to all the input fields.
You can add style="display:table-column;" to the fieldset as a workaround.
Related
Is there a way to disable margin-collapsing altogether? The only solutions I've found (by the name of "uncollapsing") entail using a 1px border or 1px padding. I find this unacceptable: the extraneous pixel complicates calculations for no good reason. Is there a more reasonable way to disable this margin-collapsing?
There are two main types of margin collapse:
Collapsing margins between adjacent elements
Collapsing margins between parent and child elements
Using a padding or border will prevent collapse only in the latter case. Also, any value of overflow different from its default (visible) applied to the parent will prevent collapse. Thus, both overflow: auto and overflow: hidden will have the same effect. Perhaps the only difference when using hidden is the unintended consequence of hiding content if the parent has a fixed height.
Other properties that, once applied to the parent, can help fix this behaviour are:
float: left / right
position: absolute
display: inline-block / flex / grid
You can test all of them here: http://jsfiddle.net/XB9wX/1/.
I should add that, as usual, Internet Explorer is the exception. More specifically, in IE 7 margins do not collapse when some kind of layout is specified for the parent element, such as width.
Sources: Sitepoint's article Collapsing Margins
One neat trick to disable margin collapsing that has no visual impact, as far as I know, is setting the padding of the parent to 0.05px:
.parentClass {
padding: 0.05px;
}
The padding is no longer 0 so collapsing won't occur anymore but at the same time the padding is small enough that visually it will round down to 0.
If some other padding is desired, then apply padding only to the "direction" in which margin collapsing is not desired, for example padding-top: 0.05px;.
Working example:
.noCollapse {
padding: 0.05px;
}
.parent {
background-color: red;
width: 150px;
}
.children {
margin-top: 50px;
background-color: lime;
width: 100px;
height: 100px;
}
<h3>Border collapsing</h3>
<div class="parent">
<div class="children">
</div>
</div>
<h3>No border collapsing</h3>
<div class="parent noCollapse">
<div class="children">
</div>
</div>
Edit: changed the value from 0.1 to 0.05. As Chris Morgan mentioned in a comment bellow, and from this small test, it seems that indeed Firefox takes the 0.1px padding into consideration. Though, 0.05px seemes to do the trick.
You can also use the good old micro clearfix for this.
#container::before, #container::after{
content: ' ';
display: table;
}
See updated fiddle: http://jsfiddle.net/XB9wX/97/
Actually, there is one that works flawlessly:
display: flex;
flex-direction: column;
as long as you can live with supporting only IE10 and up
.container {
display: flex;
flex-direction: column;
background: #ddd;
width: 15em;
}
.square {
margin: 15px;
height: 3em;
background: yellow;
}
<div class="container">
<div class="square"></div>
<div class="square"></div>
<div class="square"></div>
</div>
<div class="container">
<div class="square"></div>
<div class="square"></div>
<div class="square"></div>
</div>
overflow:hidden prevents collapsing margins but it's not free of side effects - namely it... hides overflow.
Apart form this and what you've mentioned you just have to learn live with it and learn for this day when they are actually useful (comes every 3 to 5 years).
I know that this is a very old post but just wanted to say that using flexbox on a parent element would disable margin collapsing for its child elements.
CSS*
Fixes
display: flow-root;
✅ Parent element collapse❌ Sibling element collapse
display: flex;flex-direction: column;
✅ Parent element collapse✅ Sibling element collapse
*Modern browsers (excluding IE11) support display: flow-root and display: flex.
Examples
section {
background: green;
outline: 2px solid purple;
}
p {
background: yellow;
margin: 1em 0;
}
section.flow-root {
display: flow-root;
}
section.flex {
display: flex;
flex-direction: column;
}
<h2>Default</h2>
<section>
<p>Paragraph 1</p>
<p>Paragraph 2</p>
</section>
<h2><code>flow-root</code> (Fixes only container)</h2>
<section class="flow-root">
<p>Paragraph 1</p>
<p>Paragraph 2</p>
</section>
<h2><code>flex</code> (Fixes both container & siblings)</h2>
<section class="flex">
<p>Paragraph 1</p>
<p>Paragraph 2</p>
</section>
Every webkit based browser should support the properties -webkit-margin-collapse. There are also subproperties to only set it for the top or bottom margin. You can give it the values collapse (default), discard (sets margin to 0 if there is a neighboring margin), and separate (prevents margin collapse).
I've tested that this works on 2014 versions of Chrome and Safari. Unfortunately, I don't think this would be supported in IE because it's not based on webkit.
Read Apple's Safari CSS Reference for a full explanation.
If you check Mozilla's CSS webkit extensions page, they list these properties as proprietary and recommend not to use them. This is because they're likely not going to go into standard CSS anytime soon and only webkit based browsers will support them.
Try
{
display:flex;
flex-direction:column;
}
or
{
display:grid;
}
I had similar problem with margin collapse because of parent having position set to relative. Here are list of commands you can use to disable margin collapsing.
HERE IS PLAYGROUND TO TEST
Just try to assign any parent-fix* class to div.container element, or any class children-fix* to div.margin. Pick the one that fits your needs best.
When
margin collapsing is disabled, div.absolute with red background will be positioned at the very top of the page.
margin is collapsing div.absolute will be positioned at the same Y coordinate as div.margin
html, body { margin: 0; padding: 0; }
.container {
width: 100%;
position: relative;
}
.absolute {
position: absolute;
top: 0;
left: 50px;
right: 50px;
height: 100px;
border: 5px solid #F00;
background-color: rgba(255, 0, 0, 0.5);
}
.margin {
width: 100%;
height: 20px;
background-color: #444;
margin-top: 50px;
color: #FFF;
}
/* Here are some examples on how to disable margin
collapsing from within parent (.container) */
.parent-fix1 { padding-top: 1px; }
.parent-fix2 { border: 1px solid rgba(0,0,0, 0);}
.parent-fix3 { overflow: auto;}
.parent-fix4 { float: left;}
.parent-fix5 { display: inline-block; }
.parent-fix6 { position: absolute; }
.parent-fix7 { display: flex; }
.parent-fix8 { -webkit-margin-collapse: separate; }
.parent-fix9:before { content: ' '; display: table; }
/* Here are some examples on how to disable margin
collapsing from within children (.margin) */
.children-fix1 { float: left; }
.children-fix2 { display: inline-block; }
<div class="container parent-fix1">
<div class="margin children-fix">margin</div>
<div class="absolute"></div>
</div>
Here is jsFiddle with example you can edit
To prevent margin collapsing between siblings, add display: inline-block; to one of the siblings (one is enough though you can add it to both).
For your information you could use
grid but with side effects :)
.parent {
display: grid
}
I want to style only the content area of a div having a padding to visualize its content boundary like the inner box in the dev-tools is colored by the web browser. I've tried many things but either the css recommendations are not yet implemented like or maybe I use it in the wrong way.
<div class="around">
<div class="div-with-padding outline-content">
stuff ...
</div>
</div>
.around { margin: 50px auto; width: 400px; padding: 0px; }
.div-with-padding { min-height: 200px; padding: 15px; }
I've added an outline to the div just for comparison. The position: relative below is needed because its child's max-height/width only fits to the matched div if its position is relative.
.outline-content {
outline: 1px solid red;
position: relative; /* in the original post I've used bootstrap instead */
}
I've found no way to do this within the original div so I've added a pseudo-element.
First try:
.outline-content::before {
content: '';
position: absolute;
width: max-content; height: max-content;
outline: 1px dotted blue;
}
I don't really understand how max-content works. I've tried also others mdn. Maybe it doesn't work because I've set position: absolute; to don't change the page itself.
Second try:
.outline-content::before {
content: '';
position: absolute;
width: calc(100% - 30px); height: calc(100% - 30px);
outline: 1px dotted blue;
}
The question is how to get parent's padding = 30px if it isn't always the same. I've tried much more but without success.
I know with jQuery this problem becomes easy. If anybody knows an answer using only css … I really like to know it. Please also correct mistakes in my code snippets (width: max-content; and the like).
Thanks!
(this post includes some adaptions to the comments)
The magic css-property is called "background-clip".
HTML
<div class="outer">
outer-content
<div class="inner">
inner-content
</div>
</div>
CSS
.outer {
display:inline-block;
background-color: red;
border: 1px solid black;
padding: 10px;
}
.inner {
width: 100px;
height: 100px;
padding: 10px;
background-clip: content-box;
-moz-background-clip: content-box;
background-color: green;
border: 1px solid black;
}
Example: http://jsfiddle.net/u2vyqdc6/2/
As you can see:
One surrounding div with some content and some padding so you can see better what's going on.
Inside is another div with content, padding and "background-clip: content-box".
"background-clip" works just like "(-moz-)border-box". It tells the browser how to handle the background-specific box-model.
And the best thing?
Browser-support is almost universal at 95%:
http://caniuse.com/#feat=background-img-opts
This question already has answers here:
Impact of border property on top margin
(3 answers)
Closed 7 years ago.
EDIT: found a very good link explaining all about border collapse:
border collapse explained with examples
End of edit. Enjoy :)
I am failing to understand this...
Why applying a 1px solid black border to my div changes the div's size by a lot?
(without the border I can see a relatively thin line as my back ground color, with the border the רectangle of the background color is much wider, see the pictures)
this pic is without applying the border:
and now look at this photo (the only difference is the border...)
can someone explain how the border influences so much on the div size / what is really happening here?!
style:
#header {
background-color: yellow;
color: white;
text-align: center;
border: 1px solid black;
}
here is a fiddle so you can play around:
my fiddle
Thanks a lot,
Jimmy.
That's because of margin collapsing.
The margin is not part of the element iself, it's the distance between the element and surrounding elements, or between the element and containing borders or paddings.
In the first image the margins of your header element (a h1 perhaps?) is collapsing outside the div. The margins doesn't affect the size of the div, instead it pushes the surrounding elements away.
When you add a border to the div, then the margins of the header element will push the border away from the header element instead of pushing surrounding elements away. The margins of the header element determine the size of the div.
The Header size is same, just the background will not fill the area specified as element margin. Your h1 has default margin at top and bottom which is not calculated by browser to be filled. In order to force it you can use overflow: hidden; on Header, an old trick that covers 99% of famous clearfix class (for float fix):
#header {
background: yellow;
overflow: hidden;
}
#sidebar {
float: left;
width: 30%;
background: green;
}
#content {
float: left;
width: 70%;
background: lime;
}
<div id="header">
<h1>Header</h1>
</div>
<div id="sidebar">
<h1>Sidebar</h1>
</div>
<div id="content">
<h1>Content</h1>
</div>
The other way would be to avoid h1 margin and use padding instead, or fixed height:
#header {
background: yellow;
}
#sidebar {
float: left;
width: 30%;
background: green;
}
#content {
float: left;
width: 70%;
background: lime;
}
h1 {
margin: 0;
padding: .8em 0;
}
<div id="header">
<h1>Header</h1>
</div>
<div id="sidebar">
<h1>Sidebar</h1>
</div>
<div id="content">
<h1>Content</h1>
</div>
You can add box-sizing to prevent this from happening. Not every browser supports it though.
html {
-moz-box-sizing: border-box;
box-sizing: border-box;
}
*, *:before, *:after {
-moz-box-sizing: inherit;
box-sizing: inherit;
}
The total size of an element is going to be defined by:
Margin>Border>Padding>Actual element size
Your browser's developer console should allow you to see the value of all of these so try and see which one is changing between those two instances. From the pictures provided it looks like the padding may be changing as you manually adjust the border.
Try manual setting these values:
#header{
border: 1px;
border-color: black;
margin: 0;
padding: 0;
}
Set margin on the h1 tag to 0:
h1 {
margin:0;
}
I updated your fiddle here
Perfect example why sometimes using outline instead of border can solve a lot of headache.
Outlines differ from borders in the following ways:
Outlines do not take up space, they are drawn above the content.
With much respect to all other solutions (which are important to understand), try using the following as an easy fix:
outline: 1px solid black;
instead of
border: 1px solid black;
JSFiddle
Cheers!
div {
box-sizing: border-box;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
border: 1px solid yellow;
}
Found an interesting browser behaviour. Given the following code:
div {
padding: 5px 10px;
color: #FFF;
}
.a {
float: left;
/* fix either set width or remove float */
background: goldenrod;
}
.b {
position: relative;
overflow: hidden;
background: #392;
}
.b div {
width: 20000em;
background: #942;
}
and
<DIV class="a">
<DIV class="b">
<DIV>Content</DIV>
</DIV>
</DIV>
I would expect the overflow: hidden to hide/crop the div to the viewport, but the parent float is honoured instead and the page is WIIIIIIIDE.
Anyone know if this a feature or a browser bug?
I know that you should add a width to a float ... but this felt weird to me. To stop the behaviour, either remove the float on .a or add max-width: 100% or similar.
[Note: found in html spaghetti mixing ektron, jcarousel with bootstrap, this is simplest test case to reproduce issue.]
Demo at http://codepen.io/elliz/pen/wteya
I searched for this but I can't seem to find a similar case that had an answer to it. Sorry if it has been addressed previously.
I have a section of a html page that looks, on a basic level, like this:
<div id=wrap>
<div id=lb>
Content
</div>
<div id=rb>
Content
</div>
</div>
These basically break up my body into a left section (LB) and a right section (RB).
With corresponding CSS (Not showing a CSS Reset, but a generic one is in use as well; ... indicate other code is present but N/A):
#bwrap {
width: 100%;
height: 400px;
display:inline-table;
...
}
#lb {
width: 71.5%;
display: table-cell;
...
}
#rb {
width: 28.5%;
display: table-cell;
padding: 30px 6px 7px 6px;
border-left: 1px #6A6A6A solid;
border-right: 1px #6A6A6A solid;
}
I started right to left and filled in content in #RB; everything was perfect. However as soon as I started working in #LB I noticed that all my content within #RB shifted down to line up with the bottom of #LB's content. Even though the content nor the DIV overlaps.
The specific content that did this was a google calendar embed into #LB.
Everything looks completely normal except the shift down in #RB.
Anyone know where I went wrong? I tried to mess with floats and absolute positioning but none of it had any effect, most of it actually made the situation worse.
Use this
vertical-align: top;
Live example http://jsfiddle.net/wfyVy/
It's jumping down because the extra padding and border you have defined to rb is adding to the overall width of the container, making it no longer 28.5%. Try this:
#lb {
width: 70%;
display: table-cell;
...
}
#rb {
width: 20%;
display: table-cell;
padding: 30px 6px 7px 6px;
border-left: 1px #6A6A6A solid;
border-right: 1px #6A6A6A solid;
oveflow:hidden;
}
Update: if changing it to the css above is not enough, try adding a float: left to both ids above.
When you use paddings in elements with width % values, the paddings adds to the width value. Try reducing a little bit the width to get a correct proportion.
Don't use display: table-cell, it's ugly and doesn't work consistently on all browsers, You should be able to do fine with floats and widths.
Also using padding or margins on the same element as an element that has a width defined is not a good idea, again browser incompatibilities make it a nightmare to work with.
I suggest you do something like:
<div id="wrap">
<div id="lb">
content
</div>
<div id="rb">
<div id="rp">
more content
</div>
</div>
</div>
with css:
#wrap {
width: 100%;
height: 400px;
display: block;
...
}
#lb {
width: 71.5%;
display: inline; //not actually necessary
float: left;
...
}
#rb {
width: 28.5%;
display: inline; //again not necessary
float: right;
}
#rp{
border-left: 1px #6A6A6A solid;
border-right: 1px #6A6A6A solid;
padding: 30px 6px 7px 6px;
}