CSS Inline margin issue - css

Hopefully an easy one.
I am concentrating heavily on the CSS side of things in my project, but am having an issue with block vs inline elements, and I don't really want to move on as I know it's fundamental to learning CSS. So the misunderstanding...
I have a span element which is inline.
<span>Please Login With Your Details Below</span>
There is a margin-left of 40px on this span which shows
However if I shrink the viewport small enough it does this
Issue: So on the new line it doesn't keep the margin...
However if I change the span to display:block it does this
which is what I want.
However I read this on https://www.impressivewebs.com/difference-block-inline-css/ regarding inline elements
Will ignore top and bottom margin settings, but will apply left and
right margins, and any padding
So it may be that I have misread it totally, but from what I understand it should have applied the left margin. Can someone explain why it didn't?
Thanks

When the user agent decides that inline content cannot fit the containing block, it will split the inline content into multiple inline boxes in order to accommodate the wrapping required to properly display without overflowing the containing block (if possible).
So in your example, Please Login With Your Details Below would overflow the containing element when you shrink the viewport, and therefore gets broken into two inline boxes:
Please Login With Your Details and Below.
According to the W3C recommendation:
When an inline box is split, margins, borders, and padding have no visual effect where the split occurs (or at any split, when there are several).
They provide this specific example that demonstrates what you are encountering:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<HTML>
<HEAD>
<TITLE>Example of inline flow on several lines</TITLE>
<STYLE type="text/css">
EM {
padding: 2px;
margin: 1em;
border-width: medium;
border-style: dashed;
line-height: 2.4em;
}
</STYLE>
</HEAD>
<BODY>
<P>Several <EM>emphasized words</EM> appear here.</P>
</BODY>
</HTML>
The margin is inserted before "emphasized" and after "words".
The padding is inserted before, above, and below "emphasized" and after, above, and below "words". A dashed border is rendered on three sides in each case.

Your described behaviour is totally fine and correct.
However, the information is correct that left and right margins are applied to the inline element.
The information you did not had is, that actually inline elements left margin only indent the first line.
Think of it as an element meant to be in one single line, where this line can have horizontal margin. Having the text break in multiple line is a nice feature. But from the point of view of the margin property its still one a line.

You can use this property
text-align: justify;
text-align-last: justify;

Related

Do vertical margins collapse reliably and consistently across all browsers?

I'm trying to understand the effect that margin has on two elements. I have the following HTML, see the dabblet:
<p>some text</p>
<pre>some code</pre>
I have the following CSS:
body { color: white; }
p { background: red; margin-bottom: 50px; padding: 20px; }
pre { background: purple; margin-top: 40px; padding: 20px; }
So I've given the paragraph tag a bottom margin of 50px, and I've given the pre tag a top margin 40px. I was expecting therefore to find 90px vertical distance between them, but only have 50px.
I understand that the margins are collapsing, and that if I want to fix this then I need to add display: inline-block to the pre tag. But that causes the width of the pre tag to collapse.
Again, I know that I can fix the width problem by adding width: 100% to my pre tag, but I've got padding on the pre tag (20px), so this causes my elements to be too wide. I know that I can use box-sizing to deal with that, but what an almightly pain in the crotch it is to have to mess about with width, display and box-sizing just to have the desired amount of vertical space between two elements. So I simply refuse to do any of that.
Instead, I've decided that I'm just going to add margin-top: 90px to my pre tag, which will guarantee that I've got the 90px space that I want.
My question is: Are there any browsers out there that don't collapse margins in the way the others do? Will I inadvertently end up with 140px space (90px from the top-margin of the pre tag + 50px from the bottom margin of the paragraph tag)? In other words, are margins collapsed reliably and consistently across all browsers, or is there a browser out there that does it's own thing?
It's hard to give a definitive answer to this question because it's very broad. "All browsers" is a lot of browsers. There could always be some fringe browsers you never heard of that handle this differently. It all depends on how the browser's CSS rendering engine was written.
That said, any browser that wants to be taken seriously will try to adhere the W3C specs, which have the following to say about margin collapsing:
In CSS, the adjoining margins of two or more boxes (which might or might not be siblings) can combine to form a single margin. Margins that combine this way are said to collapse, and the resulting combined margin is called a collapsed margin.
Adjoining vertical margins collapse, except:
Margins of the root element's box do not collapse.
If the top and bottom margins of an element with clearance are adjoining, its margins collapse with the adjoining margins of following siblings but that resulting margin does not collapse with the bottom margin of the parent block.
Horizontal margins never collapse.
Source: Box Model (w3.org)
I figured it'd be a nice addition to just put your code to the test in as many browsers as possible. I made a test page page of your html (slightly modified), with an absolutely positioned 50px high block that should fit right in between the collapsed margin, to make it easier to spot a difference:
http://files.litso.com/playground/margin.html
Then I ran this through browsershots.org to get screenshots of how browsers would display this piece of HTML:
http://browsershots.org/http://files.litso.com/playground/margin.html#
(I have no idea how long this will stay cached, but I guess you could always just run it again)
Interestingly, the positioning of the blue block is a few pixels off in a bunch of the screenshots. You can still tell the margins are collapsed correctly, but I do wonder what exactly the problem is with the positioning.
The only browsers that don't seem to collapse the margin correctly are Dillo 3.0.2 and Links 2.7 on Debian 6.0, neither of which seem to listen to padding or margin properties at all (nor to the absolute positioning for that matter). They would mess up your layout no matter what, and you shouldn't worry about it. People use browsers like these for a specific reason, and seeing your page exactly as you intended it to be seen is not one of them.
TL;DR: Yes, it's safe to say that all browsers collapse these elements reliably and consistently.

CSS white-space: no wrap, no horizontal scrollbar and maintain white-space when copied

I'm trying to achieve a combination of three goals...
Determine if I should use <code><pre>...</pre></code> or <pre><code>...</code></pre>?
Make code not wrap, not create horizontal scrollbars and not overflow any parent element.
Ensure that when a visitor copies code that the white-space is maintained when they paste it in to any (competent) editor.
So far I've had the most luck with white-space: pre-wrap; however I do not want the text to wrap. If they're interested enough they'll copy-paste it for themselves. While I do not want it to wrap I also do not want it to make the element overflow outside of any parent element and I don't want the text to appear outside of it's direct parent element.
I'd be okay with a horizontal scrollbar for the code itself (pre or code element, whichever) though I'd generally prefer not to.
Just in case it's relevant I don't use any CSS frameworks or the likes, I only do a basic reset...
* {border: 0px; margin: 0px; outline: none; padding: 0px; }
I test in Firefox, then Chrome, then (actual) Opera and then maybe IE if I have sanity to spare. Thoughts please?
On number 2 and 3: Hopefully I haven't misunderstood your question--I got what I understood your goal to be working easily by by adding a fixed width and overflow:hidden to the css class.
On 1: it's working with <pre (outer)><code (inner)> so... hey.
http://jsfiddle.net/A2zhH/2/
FYI, border: gray; isn't doing anything. You need to use the format border:1px gray solid;
Goal 1 is simple: code inside pre is valid, pre inside code is not. On the other hand, pre is what matters here. You can use code inside it as a matter of principle if the content is computer code.
Goal 2 is self-contradictory as such, unless you are referring to an idea of reducing font size so that everything fits. More realistically, with regard to the statement that it is okay to have a horizontal scroll bar for the code block, use just
pre { width: 100%; overflow: auto }
This causes a horizontal scroll bar to appear for the block, instead of overflowing the content.
Goal 3 is achieved when you use normal spaces. What is copied contains spaces, and what happens to them after paste depends on the software.
I got it working to an accuracy of about 99.8% of the time using the following...
XHTML
<pre><code>/* Code here. */</code></pre>
CSS
pre {white-space: pre; width: 75vmax;}

CSS margins add up or are combined?

Let's assume that we have the following code:
<div style="margin-bottom:100px;">test</div>
<div style="margin-top:100px;">test</div>
I noticed that sometimes it creates 100px of margin between elements and sometimes it's 200px (when we use certain settings that I'm not familiar with). I can't find any information about that in the specification. What does this depend on?
If we have h1 and p in a blank document then the margin of h1 will be combined with the margin of p. They will not add up. Whichever is larger will be used.
This is happening because your margins are allowed to collapse. Certain margins may overlap (mostly block elements) and form a combined margin defined by the larger of the two values defined in the computed element style rules - that's what is happening here. This section from the CSS Box Model document explains it in detail.
Edit: As a point of interest, you can get around this (ie. break the collapsible margins) without breaking things (much?)in a couple of ways
Making the elements width: 100%; display: inline-block
Putting a height: 0; width: 0; overflow: hidden block in between the elements and putting a dot or something in it.
I forked ashley's fiddle to demonstrate. There are probably other methods but these are a quick a dirty way to get around collapsible margins if you need to.

IE6 website display problem (background or padding issue?)

I'm trying to get a website to display properly in IE6 and IE7. Here is a screenshot of how it looks in IE6.
alt text http://img225.imageshack.us/img225/4779/screenshot20091006at239.png
IE8, Safari, Firefox, etc. all display this site correctly. Could someone give me a hint as to what is causing the distortion in IE6?
If you want to take a look at the page source, the site is: www.devaswami.com
Get the CSS from here.
You're using an auto-layout table for the navbar, and it has colspans. This confuses IE, which is not very good at working out how big tables need to be when there are colspans. It makes the table wider than you need, which makes your cells wider than expected, which makes the ugly yellow background show through and it doesn't line up.
To fix it, set the style table-layout: fixed; width: 970px; on the table element, and add one <col> element for each column, each with a width: ...px style that tells IE exactly how big to make each column. Then it can't make any mistakes (and also larger fixed table layouts render faster).
To fix it better, drop the layout table and use positioned divs for the nav links. You could then also lose the silly image slicing and have a single GIF for the whole header background with the photo and links positioned over the top of that.
(Also it is worth fixing the validation errors both in the HTML and in the CSS. You are using // as a single-line comment in your stylesheet, but there is no such thing in CSS; you will only confuse the parser into dropping rules.)
Ummm at a glance, you have something that is float left and you have a margin left on it?
#foo {
float: left;
margin-left: 20px; //20px in all browsers except IE6 where it will be 40px;
display: inline; //this will fix this issue
}
There's a lot of possibilities and it's hard to just guess based on the screensnap. However, one big step towards making IE 6 and 7 behave better is to declare the doctype at the top of the document:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
That's for HTML 4.01, you'd have to update it to match what you're specifically using if it's not HTML (i.e. XHTML). That alone helps with some of the basic problems, but not all of them. If that doesn't do it, Google "IE6 css hacks" and you'll find lots of potential information that may apply to your context.
Edit: I suggest you fix the errors related to missing/improper end tags:
Error Line 199, Column 194: end tag
for element "a" which is not open
Error Line 200, Column 49: end tag
for element "p" which is not open
Source: http://validator.w3.org/check?uri=http%3A%2F%2Fdevaswami.com%2F&charset=(detect+automatically)&doctype=Inline&group=0
After that's done we can deduce that it's not a markup related issue.
Original answer:
Try applying haslayout to every element and using display:inline on any floated element:
#nav li { display:inline; } /* the selector *must* be floated and have horizontal margins in the direction of the float. */
* { zoom:1; }
For anything that was fixed by the zoom:1, apply a width/height and that will trigger hasLayout.
Though it might be useful if you actually posted some source code.

How can a URL fragment affect a CSS layout?

Compare these 3 URLs (look at the top navigation bar in each case):
http://fast.kirkdesigns.co.uk/blog
as above but with the url fragment #navigation
as above but with the url fragment #node-2655
Note, that the only difference is the URL fragment on the end.
The first two pages display absolutely fine (in Firefox at least). It's the third one where the problem lies. The fragment #node-2655 pushes the top navbar off the top of the screen. When you then scroll back up to the top of the page, the navbar has been cut in half. This happens when using any URL fragment that causes the navbar to be out of the initial viewport when the page is first loaded.
So, how can using a url fragment affect the css layout like this?!
THE SOLUTION:
as suggested below, removing the overflow: hidden on the container element that held the navbar fixed the problem. I'd love to understand why though!
Remove the overflow:hidden on #main in css_75afd7072eaf4096aaebf60674218e31.css
I'd say it's a rendering bug in FireFox as it's fine in Opera. There shouldn't be anyway an anchor would change the CSS like you say (unless you are using jQuery or something).
I am having this problem too, and think I can see what is happening.
The "column" block with the massive (5678 pixel) margin and padding makes that block very tall. In browsers other than Firefox, the positive and negative values cancel each other out, but FF really does make it that tall - kind of.
FF also knows the two cancel each other out, but seems to look at the 5678px padding and decides the column block is poking out the bottom of the #wrapper block. This is overflow - and with overflow set to auto on #wrapper, you see the true size of #wrapper with a scroll-bar down the side.
With overflow set to hidden, FF takes away the scrollbar, but still seems to scroll the contents of #wrapper so that the item the fragment points to is at the top of the page. This is normal behaviour for fragment links in scrollable blocks, but since there is no scrollbar, you cannot scroll the content back down again, hence it looks like the layout has been effected by the fragment.
So in short, I suspect that FF is operating an invisible scrollbar in this example. That could be considered a bug, but it is probably correct behaviour. Being able to scroll the content up and down inside a non-overflowed fixed-sized block using URL fragments, is a technique that can be used effectively to implement image "sliders" that work even in the absence of JavaScript.
Hope that helps. This has been puzzling me for years, and this explanation suddenly struck me out the blue. My current workaround for this is to use jQuery "scroll to" plugin to scroll the whole page down to the fragment, as this seems to prevent the contents of #wrapper from scrolling internally.
You can also take "display: hidden" off #wrapper, but your page then ends up half a mile long.
I'll just point out that there may be some weird inheritance from the 30+ stylesheets linked to in the head. There may not, either, and it's probably a rendering bug (possibly related to :target styling) that Dan suggested. I just felt it worth pointing out that if you've got more than thirty stylesheets, you likely to start seeing some weirdness, whatever else might happens.
The reason is the column with the large padding has expanded it's container, but the expansion is then hidden but overflow:hidden; but with the use of the fragment it is being scrolled into the position of the fragment, effectively chopping off anything above that. You can use javascript and set scrollTop to 0 and it scroll it back to the normal position.
Basically a wierd edge case which browsers do not seem to handle very well.
Sorry this isn't an "answer," tho it is a response to the other comments here. This problem is just flabbergasting. It is very easy to isolate (i.e., has nothing to do with number of stylesheets), and doesn't have a proper "solution," as there is no way to achieve the desired rendering.
<!DOCTYPE html>
<html>
<head>
<style>
#container {
margin: 1em auto;
width: 40em;
}
#wrapper {
overflow: hidden;
position: relative;
}
#c1 {background-color: #aaf;}
#c2 {background-color: #ccf;}
.column {
float: left;
margin-bottom: -5678px;
padding-bottom: 5678px;
width: 50%;
}
#footer {
background-color: #eee;
padding: 1px;
text-align: center;
}
p {margin: 1em;}
</style>
</head>
<body>
<div id="container">
<div id="wrapper">
<div id="c1" class="column">
<p>This is some content in a short column. We would need some Javascript to change its height if we wanted a different background color for each column to stretch the full height of the respective columns...or we can use large padding together with an equal negative margin.</p>
<ul>
<li>Jump to P1</li>
<li>Jump to P2</li>
<li>Jump to P3</li>
</ul>
</div>
<div id="c2" class="column">
<p id="p1">The desired effect is to have the height of the two columns appear the same. We use 'overflow:hidden' on the containing div (#wrapper) to wrap it around the floated columns.</p>
<p id="p2">These paragraphs have fragment identifiers. Problem comes in when clicking one of the links on the left. Instead of scrolling just the page, the browser scrolls the div with 'overflow:hidden' so the target is at the top. It does this even if the target is already visible.</p>
<p id="p3">Opera does not exhibit this behavior. This occurs in Chrome/Safari, Firefox, and IE. (Interestingly, IE also works as expected if we completely remove the DOCTYPE declaration.)</p>
</div>
</div>
<div id="footer">
<p>Footer stuff.</p>
<p>To see why 'overflow: hidden' (or any other piece of the CSS) is needed, just try disabling it.</p>
</div>
</div>
</body>
</html>
Just as a side-note, the above technique is generally used to provide flexible-width mulit-column layouts. This is probably becoming less important these days as fixed-width layouts are becoming a lot more comment - browsers are able to magnify the web page to see small text, and fixed-width makes it a lot easier to control the typography of a page, e.g. set the width (in ems) to display the ideal nine words per line regardless of what font size and magnification the user chooses.
Sorry if that does not sound like an answer, but it is basically suggesting to discard this old model and consider moving to fixed-width columns (which is a whole new subject).
I was able to solve this with some javascript to scroll the body to the position the overflow hidden element was scrolled to.
setTimeout(() => {
let intendedScroll = document.getElementById("fragmentfix").scrollTop;
document.getElementById("fragmentfix").scrollTop = 0;
window.scrollTo(0, intendedScroll);
}, 0)

Resources