I have seen a lot of css which uses margin-right: -4px to get rid of the space between inline-divs. Why is -4 being used? And is it going to work everywhere?
-4 is used when the width of a space is 4 pixels. It's completely arbitrary, completely dependent on the font metrics (family, size, etc), and therefore by definition not going to work everywhere.
It's this utterly arbitrary value that makes this one of those workarounds that really highlights the fatal flaw of using inline-blocks for (horizontal) block layout in the first place.
This is how inline-block works. if you want your divs stay in the block but be inline you can use inline-block, there are more tricks to fix this, one of them is margin-left: -4px, you can find more from the link here:
https://css-tricks.com/fighting-the-space-between-inline-block-elements/
I suggest to use CSS Grid to create blocks for layout. Here is a website to find some example for CSS Grid:
https://gridbyexample.com/examples/
Related
Now I know there are similar questions posted, but I'm looking for a solution for pixel perfection.
Sandbox: http://jsfiddle.net/unqc4a0f/1/
Problem trying to solve:
Attempted code:
.mi{float:left; width:150px;height:200px;padding-right:10px;/*margin-top:3px;*/}
.mt{float:left; width:400px;margin:0;}
In the past I've used the padding/margin hacks to push the image or the text objects down a few pixels to make them visually align at the top edge. And by visually I mean that I know that the fonts have a size and line height, but even taking that into account, the height of the actual font characters may include some space. This you can see in my example above. I've also —based on other threads here —tried using line-height, and although that did achieve pixel perfect alignment, it mangled the the vertical line spacing of the entire paragraph.
My question essentially is whether to continue using the padding/margin hacks or is there a more 'legit' solution. I ask this in regards to building layouts that are responsive and then having no issues with uniform layouts.
Thanks in advance.
Realize it's an old question but...
In CSS one can use a ::before element add a negative margin-top value to it.
Specifically, I wanted to share this Interactive Text-Crop tool I found that helps create a SASS mixin for this purpose.
The gist in this tool is that you remove the capital height from the (font-size * line-height) and then divide by two. But that is a simplification of how your font may or may not be structured.
In reality - There is no "pixel-perfect" answer because when it comes down to it, the physical structure of fonts doesn't always match their font-size and different font-families at the same font-sizes can still look taller or shorter.
Instead of float use a display:table; layout for a perfect inline placement and vertical alignment.
It only requires that you wrap them within an element...
Updated JSFiddle
.wrapper {
display: table;
}
.mi{width:200px;height:200px;display: table-cell;}
.mt{display: table-cell;vertical-align:middle;}
<div class="wrapper">
<img src="http://www.thehollywoodnews.com/wp-content/uploads/2839335-morgan_freeman_wallpaper_4_normal.jpg" class="mi">
<p class="mt">Join me in San Diego at the Global Event for Data-Driven Engagement Marketers. DMA is doing great work to protect marketers around the world, come and hear from leading marketers how DMA is enabling them to NOT MARKET ALONE</p>
</div>
The space is supposed to be there it normally comes from line height which is something you need. If you font size is 14px and you reduce the linee-height to 11px you see the gap will vanish from the top, but the text will look very cramped..
Sometimes to get pixel perfect you have to just tweak like you have with the margin on the image..
Normally, when we want to have multiple DIVs in a row we would use float: left, but now I discovered the trick of display:inline-block
Example link here.
It seems to me that display:inline-block is a better way to align DIVs in a row, but are there any drawbacks? Why is this approach less popular then the float trick?
In 3 words: inline-block is better.
Inline Block
The only drawback to the display: inline-block approach is that in IE7 and below an element can only be displayed inline-block if it was already inline by default. What this means is that instead of using a <div> element you have to use a <span> element. It's not really a huge drawback at all because semantically a <div> is for dividing the page while a <span> is just for covering a span of a page, so there's not a huge semantic difference. A huge benefit of display:inline-block is that when other developers are maintaining your code at a later point, it is much more obvious what display:inline-block and text-align:right is trying to accomplish than a float:left or float:right statement. My favorite benefit of the inline-block approach is that it's easy to use vertical-align: middle, line-height and text-align: center to perfectly center the elements, in a way that is intuitive. I found a great blog post on how to implement cross-browser inline-block, on the Mozilla blog. Here is the browser compatibility.
Float
The reason that using the float method is not suited for layout of your page is because the float CSS property was originally intended only to have text wrap around an image (magazine style) and is, by design, not best suited for general page layout purposes. When changing floated elements later, sometimes you will have positioning issues because they are not in the page flow. Another disadvantage is that it generally requires a clearfix otherwise it may break aspects of the page. The clearfix requires adding an element after the floated elements to stop their parent from collapsing around them which crosses the semantic line between separating style from content and is thus an anti-pattern in web development.
Any white space problems mentioned in the link above could easily be fixed with the white-space CSS property.
Edit:
SitePoint is a very credible source for web design advice and they seem to have the same opinion that I do:
If you’re new to CSS layouts, you’d be forgiven for thinking that
using CSS floats in imaginative ways is the height of skill. If you
have consumed as many CSS layout tutorials as you can find, you might
suppose that mastering floats is a rite of passage. You’ll be dazzled
by the ingenuity, astounded by the complexity, and you’ll gain a sense
of achievement when you finally understand how floats work.
Don’t be fooled. You’re being brainwashed.
http://www.sitepoint.com/give-floats-the-flick-in-css-layouts/
2015 Update - Flexbox is a good alternative for modern browsers:
.container {
display: flex; /* or inline-flex */
}
.item {
flex: none | [ <'flex-grow'> <'flex-shrink'>? || <'flex-basis'> ]
}
More info
Dec 21, 2016 Update
Bootstrap 4 is removing support for IE9, and thus is getting rid of floats from rows and going full Flexbox.
Pull request #21389
While I agree that in general inline-block is better, there's one extra thing to take into account if you're using percentage widths to create a responsive grid (or if you want pixel-perfect widths):
If you're using inline-block for grids that total 100% or near to 100% width, you need to make sure your HTML markup contains no white space between columns.
With floats, this is not something you need to worry about - the columns float over any whitespace or other content between columns. This question's answers have some good tips on ways to remove HTML whitespace without making your code ugly.
If for any reason you can't control the HTML markup (e.g. a restrictive CMS), you can try the tricks described here, or you might need to compromise and use floats instead of inline-block. There are also ugly CSS tricks that should only be used in extreme circumstances, like font-size:0; on the column container then reapply font size within each column.
For example:
Here's a 3-column grid of 33.3% width with float: left. It "just works" (but for the wrapper needing to be cleared).
Here's the exact same grid, with inline-block. The whitespace between blocks creates a fixed-width space which pushes the total width beyond 100%, breaking the layout and causing the last column to drop down a line.
Here' s the same grid, with inline-block and no whitespace between columns in the HTML. It "just works" again - but the HTML is uglier and your CMS might force some kind of prettification or indenting to its HTML output making this difficult to achieve in reality.
If you want to align the div with pixel accurate, then use float. inline-block seems to always requires you to chop off a few pixels (at least in IE)
You can find answer in depth here.
But in general with float you need to be aware and take care of the surrounding elements and inline-block simple way to line elements.
Thanks
There is one characteristic about inline-block which may not be straight-forward though. That is that the default value for vertical-align in CSS is baseline. This may cause some unexpected alignment behavior. Look at this article.
http://www.brunildo.org/test/inline-block.html
Instead, when you do a float:left, the divs are independent of each other and you can align them using margin easily.
I have some very simple sub-navigation that I'm trying to build across the top of the content area within my web site, but CSS doesn't seem to have any simple solutions for such a common problem: I want either 3 or 4 equally spaced DIVs across the top of the page.
1) e.g. 3 Variable-Width, Equally-Spaced DIVs
[[LEFT] [CENTER] [RIGHT]]
2) e.g. 4 Variable-Width, Equally-Spaced DIVs
[[LEFT] [LEFT CENTER] [RIGHT CENTER] [RIGHT]]
My solution for the first problem with only 3 DIVs was to float the left and right DIVs, and then assign an arbitrary size to the middle DIV and give it "margin: 0 auto". That's not really a solution, but assuming there are no changes to the navigation, it gives a rough approximation of what I want the results to be.
The solution I have for the second problem with 4 DIVs is to simply center a DIV in the same way as before, but then float two DIVs within that, e.g.
[[LEFT] [[LEFT CENTER] [RIGHT CENTER]] [RIGHT]]
But again, this requires applying an arbitrary size to the middle DIV for alignment, and if any language or image changes are made to the site, alignment values will have to be recalculated. As well, it's simply an over-complicated solution that requires merging structure with presentation.
Any help is greatly appreciated.
EDIT 07/20/2012 5:00PM
Alright, I put the "table-cell" solution into place using percents, but I encountered another issue within my slightly more complex implementation: the issue at hand is that each DIV I was referring to is actually a container for two more DIVs which are icon-label pairs, inlined either by float or by display:inline-block.
e.g. http://jsfiddle.net/c3yrm/1/
As you can see, the final element in the list is displayed improperly.
Any help is again greatly appreciated!
EDIT 07/20/2012 7:16PM
Final solution with arttronics' help: http://jsfiddle.net/CuQ7r/4/
Reference: jsFiddle Pure CSS Demo
The solution was to float the individual breadcrumbs while using a simple formula to determine the percentage of breadcrumb width based on the number total breadcrumbs.
You could use percentages, then it just comes down to simple math:
[[LEFT=22%]2% margin><2% margin[LEFT CENTER=22%]2% margin><2% margin[RIGHT CENTER=22%]2% margin><2% marginRIGHT=22%]]=100%/??px
You could then specify a width for its container and use
display:inline;
to keep them inline.
Note: If you use borders to see what the divs are doing that will add space unnaccounted for so you would need to reduce your elements width by 1% or so OR just change their background colors.
ol {
width: 400px;
/*width: 800px;*/
display: table;
table-layout: fixed; /* the magic dust that ensure equal width */
background: #ccc
}
ol > li {
display: table-cell;
border: 1px dashed red;
text-align: center
}
like here: http://jsfiddle.net/QzYAr/
One way I've found to do it is using flex boxes (or inline-flex).
Here is a great explanation and example of how it can be done.
I think in the future, flex boxes will be the superior way of handling this sort of thing, but until other browsers catch up with Mozilla's way of thinking for how to use the flex-basis attribute (with min-content, max-content, fit-content, etc. as values), these flex boxes will continue to be problematic for responsive designs. For example, occasionally the inner content (a_really_really_long_word) can't fit in the allotted space when the window is squished down, and so sometimes some things might not be visible off to the right of the screen if you're not careful.
I think perhaps if you make use of the flex-wrap property, you might be able to ensure everything fits. Here is another example of how this might be done (in Mozilla browsers anyway).
I tend to use flex boxes for letterheads or tables where the width is fairly fixed (not too small) because they usually space themselves nicely; I tend to use nested float and inline-block objects for websites where the content must squish down very small (as suggested in some of the other answers here).
I have an issue that terrorizes me in my sleep, unrelentingly . If you have an attainable solution and care to share it, please do; I'd like to have a normal night of sleep again.
On my latest project, there are multiple times when I will need to have 4 or 5 elements floated next to one another. Each element must be sized using percentages (%) but must also have border-right: 1px solid #000.
Once upon a time, I would normally size each element with percentages, then create a child element that would have all of the styling properties that the parent probably should have had, including the border-right. This solution isn't ideal, however, because it involves a lot of unnecessary markup.
A co-worker then directed me to another solution. When an element has a width that is sized using %s, and also needs to have border-right: 1px solid #000, apply margin-right: -1px as an offset. And while it works, it created another issue for me (which is why we're here, together, in union).
When zooming out in any of the major browsers (ctrl mousescroll, ctrl -), the floated elements that have been the focus-of-discussion tend to dance around a bit; the last element toggles between breaking to the next line and then snapping back. Please refer to the image below:
The reason this should be addressed is because the scope of the project has the potential of serving people from many different demographics (especially those who may need to scroll in, or out for that matter, to make the text larger or smaller). A very broad project, indeed.
How can I reach my goal highlighted in the example above?
How can I have 4 or 5 or more (or less) bordered elements floated next to one another, sized proportionally using %s, WITHOUT them breaking form?
You can use the experimental box model CSS3 declaration to have the borders detract from the elements width instead of adding on to it. This should prevent the problem. Quirksmode has a nice write up on it. It is supported by IE8/9 and current versions of webkit, opera and ff.
li {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
The basic issue here, I think, is that you're 'misusing' the width property - width is supposed to control inner boxes, not the size of outer boxes. That is, your borders are supposed to be added on to your boxes, not included in the calculated width.
The result is that you don't have many choices beyond either:
Using Javascript to do some fancy recalculation,
Seeing if you can trigger quirks mode and use the IE5 box model (NOT a good idea),
Replacing borders several background images in lots of stacked divs (not nice), or,
Floating 20% width containers, then putting width:auto divs (not width:100%) with borders in the parent floats.
I know solution 4 sounds horrible, and means non-semantic markup, but it's a common kludge and one that other developers will probably understand (too) well.
This may sound horrible, but why not use a background image to create the border?
.box_20_percent {
width:20%;
float:left;
padding:0;
background-image:url([one_pixel_colored_image]);
background-repeat:repeat-y;
background-position:right
}
This should leave the "border" out of the resize calculation altogether.
If you declare the border-width and negative margin in ems instead of pixels, there is no wrapping/jumping. I realize this may be cold comfort since it would compromise your design somewhat, but it works!
I have declared common css classes for common margin and padding classes in my css so that i can use them without making other css declarations too specific.
For example :
.padTB5{padding:5px 0;}
.pad10{padding:10px;}
.mTop10{margin:10px 0 0;}
.mTop5{margin:5px 0 0;}
Is this method right??
If not then why?
If yes then which is better margin or padding? (I know margin issues with browsers)
Please guide... thanks in advance :)
This is bad practice as classes should be semantic - that is they should describe the type of thing you are styling. For example "blog-header", "primary-this", "secondary-that" etc.
In practice, the downside to using classes as you describe is that if your visual design changes and you need different sized margins or padding, then you will need to change the class names too - which means changes to both the CSS and HTML. Or if you just change the CSS then the class names no longer describe what they're for. This approach is not much better than using inline styles.
Margins and padding are different things and behave in different ways. Margins can collapse in certain circumstances whereas padding doesn't. Padding will include background images or colours whereas margin doesn't. Borders will display between padding and margin.
In my opinion, this is not optimal, unless you do it right.
In your markup, you now have something like this:
<div class="pad10 mTop10">
and you have that all over your site.
What if you want to change your CSS to have a little extra margin/padding?
.pad10 { padding: 12px }
.mTop10 { margin: 12px 0 0 }
Oh. Those class names aren't looking so sensible anymore: you have to either put up with wrongly named selectors, or go Find and Replace in all your files.
What if you decide that some elements with .pad10 need to have red text?
.pad10 { padding: 12px; color: red }
Now the class name makes even less sense.
It might be alright to do this type of thing if you also apply a relevant (semantically sensical) class/id to each element in your HTML:
<div class="contactErrorMessage pad10 mTop10">
because that way, at least you can do:
div.contactErrorMessage { color: red }
You shouldn't do that. Naming classes like left or margintop20 is unadvised. You should use classes like content or sidebarBox, that describe the content.
Let's say you want to change the margin-top from 10px to 1em. Using your method either
mTop10 will have margin-top: 10px;
or you have to change your className to mTop1em
None of this is good.
See w3.org goodclassnames about this.
Also see w3.org about box model for margin, padding.
Margin is different then padding. Margin is the space out side the box, padding is the space inside the box. Both margin and padding are cross browser compatible. Your declarations are correct although it is not a recommended practice to create classes for margins or padding. One good use to this is creating a class for rounded corners or shadows, where you can quickly apply round corners by specifying the round corner class.