If I wrote this:
#element {
margin-top: -50px;
}
By general rule, it would move the element upwards by 50 pixels.
Recently, I accidentally used this bit of code instead:
.elements {
margin: -50px;
}
So I had these <div> tags, one beneath the other, and by writing margin: -50px; they all somehow got closer together.
But thinking in retrospect, I don't really see how this worked. The size of the elements didn't change (as far as I know, as they contained child elements, and the child elements were closer together as well), and they didn't seem to zoom in size or anything.
I did some research online, but all I could find was for negative margins on one or two sides at most.
Is there an explanation to this? What actually happens? Maybe it's because I'm using Google Chrome, and maybe nothing happens in other browsers?
Tha margin is not added to the appearance of the element but rather to its bounds, so basically your element looks e.g. 200x200 but its bounds are equal to that of an element of 100x100 since you substract 50px from every side. Try it for yourself:
Fiddle here.
HTML:
<div class="e1"><div></div></div>
<div class="e2"><div></div></div>
CSS:
body {
padding: 100px;
}
div {
width: 200px;
height: 200px;
float: left;
margin: -50px;
}
.e1 {
background: red;
}
.e2 {
background: yellow;
}
.e1>div, .e2>div {
width: 100px;
height: 100px;
outline: 1px solid blue;
margin: 50px;
}
I've added a padding to the body to make the elements be pushed down so you can see the overlap they cause. Updated so you can see the bounds of the squares that result.
Related
I am trying to make a div with text and a div with a button fit side by side. It works fine until you make the screen really narrow. Is there a way to force them to be on the same line and for the first div to shrink to accommodate the min-width of the second?
http://jsfiddle.net/C3877/9/
To see what I mean, resize the window, reducing the width, until the div with the button is forced onto the second line. That is what I'd like to prevent.
Note: I only care if a suggested fix works properly in Chrome.
Instead of floats, you could use display: inline-block. This will keep things all on one line, and respect the min-width as well.
Inline-block fiddle: http://jsfiddle.net/C3877/8/
In addition, since you only care about Chrome, you could look into flexible boxes
A (quick) flex fiddle here: http://jsfiddle.net/C3877/11/
You can use negative margin-left for the floated right element. Note that this solution keeps using float for both the left and right divs, without using float, you have dozens of solutions (as some of other answers pointed out).
#right_div {
...
margin-left:-100%;
}
Note that all the next content should be wrapped in a block element and use clear:both. I also added a sample of such an element with background:green in this DEMO.
Appending this does the trick I suppose:
#media (max-width:515px) {
#left_div { width: 100%; margin-right: -100px }
}
UPDATED
You could use margin and absolute positioning:
CSS
#parent_div {
width: 100%;
height: 10%;
position: relative;
min-width: 40px;
}
#left_div {
width: 80%;
min-width: 100px;
height: 80%;
float: left;
background-color: #000;
color: #FFF;
}
#right_div {
width: 15%;
min-width: 100px;
float: right;
background-color: blue;
position:absolute;
right: 0px;
}
input[type=button] {
font-size: 2rem;
}
SEE DEMO: http://jsfiddle.net/C3877/19/
You will have to play with some of the css to get it just right when you move it on your website. But this is a sure quick fix.
I have some css:
.note {
background: red;
}
.note > div {
max-width: 780px;
margin: 0px auto;
position: relative;
padding-left: 20px;
border: 1px solid black;
}
.note > div:before {
content: '⚠';
position: absolute;
left: 0px;
}
And a corresponding html like:
<div class='note'><div>Foobar</div></div>
This creates a red line across the screen, but the content will be only in the center area. It works well so far. But I want the whole content to be in a 800px width area, so I add a container:
#container {
max-width: 790px;
margin: 0 auto;
background: green;
border-radius: 10px;
padding: 5px;
}
And some html:
<div id='container'>
<p>Lorem ipsum</p>
<div class="note"><div>foo</div></div>
<p>Foobar</p>
</div>
Of course, note won't work here (the red line doesn't extend beyond the green container). I've been trying to come up with something, but I couldn't. I can't just close the container, place my note, and open another because border-radius and (and also box shadow, but I left it out from the example) would break then. Using a negative margin on .note also doesn't work, because it adds horizontal scrollbars. I could make .note position: absolute;, but then my note would overlap whatever comes after it.
Any ideas how could I solve it?
Update: Here's a JSFiddle. The second version is what I actually want, except that it creates a vertical scrollbar. The third is like Robert's solution, and the only problem is that it takes the div out of flow, and I'd like to avoid hacks like adding a margin-top to the following element because I don't know the length of the note in advance.
.note {
background: red;
position: absolute;
left:0;
right:0;
}
Here's a jsfiddle:http://jsfiddle.net/ySVZb/
Note that I changed some widths so it's easier to see in the jsfiddle screen, but the size is irrelevant. Also note that because I've taken the note div outside the normal flow, you will need to add an appropriate margin to anything that follows or it will fall behind the note div. Some generic like .note + * {margin-top: 2em} will work in some cases, but it will override any margin top already on that element, in those cases you'll need a more specific fix like .note + p {margin-top: 3em;} jsfiddle showing that here: http://jsfiddle.net/ySVZb/1/
I stumbled upon a difference in layout rendering between Safari and Chrome/Firefox and I don't know which one is "right".
You can check the jsfiddle here
On Firefox/Chrome the layout is as expected, the yellow div is right after the red ones. But on Safari, the yellow div is positioned under the red ones.
After investigating what I did wrong I found out the bug comes from the CSS class E whose property margin-right (value: -11px) is bigger than the width property (value: 10px) for my div.
I think I understand why Safari renders it this way. The width of div of class B is computed as being the sum of the widths of its children as they have the property float: left;.
Here it is widthB = widthB2*2 + widthE + marginRightE + widthC or marginRightE < -widthE so widthB is not large enough to contain each div next to each other.
So my questions are:
Am I right in my understanding of what Safari does?
Why do Chrome and Firefox render differently? Are they just not decreasing the width of the parent div based on a negative margin-right?
Would the proper correction to always have a margin-right lesser or equal to the width of a div in this case?
Thank you!
HTML:
<div class="A">
<div class="C">
<div class="B">
<div class="B2"></div>
<div class="B2"></div>
<div class="E"></div>
<div class="C">
<div class="D"></div>
</div>
</div>
</div>
</div>
CSS:
.A {
background-color: blue;
height: 200px;
}
.B {
height:100px;
}
.B2 {
background-color: red;
height: 100px;
width: 100px;
float: left;
}
.C {
float: left;
}
.D {
height: 40px;
width: 40px;
float:left;
background-color: yellow;
}
.E {
height: 50px;
width: 10px;
position: relative;
left: -10px;
margin-right: -11px;
background-color: black;
float: left;
}
I'm not sure what you expect to happen with the CSS in the JS fiddle. You are delving into undefined behaviour. I say this because:
'C' is floated but does not have a defined width. This leads to issues in various browsers depending on the complexity of the layout.
None of the floated elements are ever cleared. When floating it is imperative that a clearfix of some description is used, whether it is clear:both, etc.
If you tweak the mark-up and add a clear-fix, you see that the content is always 239px. See http://jsfiddle.net/eaFn9/
However, it seems like the relatively positioned item 'E' and margin is having a negative impact on the width calculation, as Chrome's web inspector seems to always report oddly for the negative margin on this element.
If you play around with this in web inspector you can see it's almost as if the negative margin is the cause of the drop. I think it may be due to a container that does not have a width, and isn't position relative in itself.
How to fix?
Personally, I would want to re-write your layout to include fixed widths on all floats, reduce nesting of floats and clear where possible. It seems overly complex but without a real world use case it's hard to rewrite.
However, It seemed to me that you can wrap 'B2' + 'E' elements in a wrapper that is floated and relatively positioned, then use absolute positioning on 'E' to give the same affect and remove the negative margin.
This is the JSFiddle I came up with: http://jsfiddle.net/jV3Ub/
Sorry, this is not really an answer but it's too long to make it a comment...
Anyway, it took me a minute to figure this out.
I used Firefox 19 on Mac OS X 10.8.2, Chrome 24.0 (Mac) and Safari 6.0.2 (Mac as well). Using the web inspector tools, I realized the divs are not computed the same way indeed. I suck at calculations, but I took the time to sit down and look at this thoroughly, and I do understand Safari's calculations the same way you do.
In Safari, it seems that div B isn't wide enough to contain the yellow div (C) so it seems to reject it to the bottom. For the record, in my tests, I see the yellow div to the right of the red div in FF and Chrome, while Safari shows it right underneath the red, and to the upper left. I am not sure this will help, but I can only recommend you to use the web inspector tools now integrated to all modern browsers to debug this.
I'm not sure about why this happens, all I know is that by only changing the width of E by 1px, like so:
.E {
height: 50px;
width: 11px; /* added 1px to this property */
position: relative;
left: -10px;
margin-right: -11px;
background-color: black;
float: left;
}
it displays correctly in Safari.
Make the following changes to classes .D and .E:
.D {
float:left;
height: 40px;
width: 40px;
background-color: yellow;
margin-left: -11px;
}
.E{
height: 50px;
width: 10px;
position: relative;
left: -10px;
background-color: black;
float: left;
}
DEMO: http://jsfiddle.net/uryJJ/22/
I hope this helps!
SECOND EDIT:
I think we should link these two questions: https://stackoverflow.com/questions/4989930/css-negative-margin and why use negative margins? to this one.
Also See the W3C spec on margin: http://www.w3.org/TR/CSS2/box.html#margin-properties.
Section 8.3.1 Might actually explain what is going on with your sample. A collapsing margin issue not rendering correctly in Safari.
ORIGINAL POSTING:
So my questions are:
1) Am I right in my understanding of what Safari does. Why do Chrome and Firefox render differently? Sounds like that might be it, but, really, who cares? You are not getting the results you want. You should change your code unless you don't care about Safari users.
2) Are they just not decreasing the width of the parent div based on a negative margin-right?
Probably, but again, not really important.
3) Would the proper correction to always have a margin-right lesser or equal to the width of a div in this case? I would say yes. To fix the issue and get the results you want I would move the div with class E inside the right most div with class B2. Then float E to the right and remove the position, left and margin-right attributes.
.E {
height: 50px;
width: 10px;
background-color: black;
float: right;
}
http://jsfiddle.net/uryJJ/32/
FIRST EDIT
.D {
height: 40px;
width: 40px;
float:left;
background-color: yellow;
position:relative;
left: -10px;
}
.E {
height: 50px;
width: 10px;
position: relative;
left: -10px;
background-color: black;
float: left;
}
http://jsfiddle.net/uryJJ/33/
Sorry, I might be beating this to death but this fixes it:
.E {
height: 50px;
width: 10px;
margin-left: -10px;
background-color: black;
float: left;
}
http://jsfiddle.net/uryJJ/35/
I was not a fan of negative margin values until just now.
I've always thought I understood margins and negative margins but apparently I don't! I've just started a new design and running into problems already.
I have a div (hill3Cont) and another div (hill3Hill) nested inside, and this is the CSS for them.
#hill3Cont
{
width: 100%;
background-image: url("images/grass.jpg");
}
#hill3Hill
{
margin: -100px 0 0 0;
height: 600px;
width: 100%;
background: url("images/hill3.png") no-repeat center top;
}
I have applied a negative margin to the top of the child div in the hope it will push this content up outside the boundaries of the parent div. But it doesn't, it doesn't move. If I apply a positive margin it pushes the parent div down along with the child inside it.
The only way I can make it behave properly is use a border or overflow hidden on the parent div, but the design won't allow for either of these (I don't want a border and overflow hidden hides the child).
Maybe it's just been a long day and I'm missing something common! Many thanks in advance.
Edit:
I have got a solution, I've put a single padding top on the parent div, padding: 1px 0 0 0. It works for my design so I'm happy but still keen to find out what's happening.
For child inside parent element use position relative and negative top instead.
http://jsfiddle.net/GEwj3/3/
#hill3Cont
{
margin-top: 50px;
width: 200px;
height: 200px;
background-color: red;
}
#hill3Hill
{
height: 50px;
width: 100px;
background: blue;
position: relative;
top: -20px;
}
I have some unexplained weirdness with a nested DIV's margin "leaking" out of the parent container .
The following test case* probably explains it best:
http://jsbin.com/ibaze
The outer wrapper (red) doesn't start at the very top - unless there's a text node or overflow: auto; on that element.
(Tested on Firefox and Safari.)
While overflow allows me to work around the issue, I'd quite like to know why it is happening in the first place.
Any insights would be appreciated!
* it's a minimal test case except for the script at the bottom, which merely illustrates the workarounds
The reason why it is not working is that your vertical margin in CSS is collapsing, which is expected behavior.
Remove the margin from #inner, and instead specify a padding: 50px; to your #outer to get the desired result:
* {
margin: 0;
padding: 0;
}
body {
color: white;
background-color: blue;
}
#outer {
padding: 50px;
background-color: red;
}
#inner {
background-color: green;
}
For more information on Vertical Margin Collapsing, I recommend you read the following article:
CSS - Auto-height and margin-collapsing