First up, for extreme clarity, here a JS fiddle demonstrating what I'm trying to achieve:
http://jsfiddle.net/bb_matt/VsH7X/
Here's the explanation - my rationale:
I'm creating a responsive site using the 1140 grid framework.
It's a fairly complex layout.
I've created a re-usable simple gallery class which can drop into any defined column size & using media queries, I apply relevant percentage widths to the li elements.
Each of the li elements has a right margin of 5%.
I'm using nth-child(xn+x) in the media queries to remove the right margin at the end of each row.
Everything works well - images resize as the layout resizes, the number of gallery items in a row work as I've defined based on percentages.
The only remaining issue to fix is to clear between rows.
I can't add additional html markup and I want to steer clear of overly complex jquery fixes.
I know of two ways to fix this, but I'm not keen on either of them.
First fix, simply using display: inline-block on the li elements, with a vertical align of top, would flow everything correctly... however, all the percentages get shot and the gallery items no longer neatly fit in the allocated space.
Second fix, give the list items a height. This is the route I will go down if necessary - it will require a different height depending on the resolution - no big deal, but not as neat.
I updated your fiddle here: http://jsfiddle.net/VsH7X/5/
I added a clear: left to the first item in each new row.
ul.gallery li:nth-child(5n+6) {
clear: left;
}
Keep in mind that the :nth-child pseudo class does not work in IE6-8, or FF3 and under.
Related
EDIT - As requested here's the Fiddle jsfiddle.net/daghene/eq4tfzLn/
I've already searched a lot on Stackoverflow and Google to find an answer to this but even if there's plenty I don't know why they're not working nor if I'm handling this layout correctly.
Basically I'm using Skeleton responsive framework to make a one-page layout and I have a section where there's a row with this image on the left and text on its right. Below it there's a small twitter paragraph with the latest news.
Basically my problem is: when the first row gets too small and the text starts getting long the image gets way too small and I thought the best solution is to vertically center it, but both it and the div's height are responsive(most solutions requires at least one of the two to be fixed height).
What's your suggestion and far more importantly am I handling this layout well on a logical perspective or is it ok to have paragraphs get THAT long with the image simply sticking to the top?
Note that it displays fine on desktop, tablet and smartphones, there's just that little part where it gets kinda weird...here's the screenshot of how my layout is acting, the third one being the one that I think should be fixed since it's kinda ugly to look at and maybe centering the image would help.
P.s. one thing I forgot, haven't put my code since Skeleton, as most responsive Frameworks, simply requires a .container class with .row and .X columns inside it to give the divs size and centering and I didn't add anything on top of that yet. The only thing I think I'll do is put the sections in a fixed height's div because I plan on making the user scroll them as slides and they'll always need to be 100% viewport height or at least a fixed height like say 600px scaling.
P.s.2 if the only solution is js since we don't know the paragraph's and img's height at all times go ahead and propose a solution, I'm asking if this could be done with CSS since I'm not that good at js yet.
I would give the thanksup row an id - eg vertical and then you can use the following styles to achieve vertical alignment:
#vertical {
display:table;
width:100%;
}
#vertical > .columns {
float:none;
display:table-cell;
vertical-align:middle
}
#media (max-width: 565px) {
#vertical > .columns {
display: block;
}
Updated fiddle
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 several divs on a page that all have the same width but different heights. They are all in one div, the #note1PreviewDiv. They all share the class .note, which has the following css code (among other):
.note{
width: 160px;
padding: 10px;
margin: 10px;
background: #e3f0ff;
float: left;
}
I thought with float: left; they would all automatically align so that they are well aligned among each other.
Here's a preview of what it looks like:
Current state http://posti.sh/img/ist.png
And here's what the positioning should be like:
Desired state http://posti.sh/img/soll.png
I think you get the idea. Somehow it seems to me the height of the leftmost div pushes the other divs in the second row to the right - but that's only guessing.
Thanks for your help!
Charles
You're not going to be able to do this easily with CSS only.
CSS3 has a new feature called column layout, but browser support is not great. IE9 and below don't support it.
See http://designshack.net/articles/css/masonry/ and the last example for CSS3 solution.
Have a look at these js / jQuery options for easier implementation and browser support:
masonry
isotope
vanilla masonry which doesn't need jQuery.
wookmark
The kind of lay out you want is really difficult (not possible?) without going for a column based approach and adding additional block elements to represent each column. This obviously won't work with a flexible number of columns if you want a dynamic layout based on screen size.
That said, you could always use JavaScript to dynamically place elements into columns, and get it to match the screen size.
Is the height of the parent container given a fixed value? If it is, try setting the height of the parent container to auto, and the overlow propery to hidden.
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'm having issues with creating equal height columns on the basic Dreamweaver HTML5 3 col fixed layout. I was using jQuery equal height columns to make the column's bg colour be equal on all pages, however due to some scripts I am using on my site and incompatibility with a manual "style:height:xpx" added to the article column I would like to try and use the display:table, display:table-cell method. I have used the basic Dreamweaver 5.5 HTML5 template, and kept everything the same except removed the display:block property for aside, article etc elements. I added a container div around the 3 columns; aside, article and aside.
Everything works fine - as in the background colour continues until the end of the block, which is what I need - except the trouble is, for some reason on the aside columns it leaves a gap at the top of the columns of 13px. I have no idea why this is happening.
I have uploaded the file here: http://www.primecuts.org.uk/test.html . If I remove the <nav> part, the gap is still there, although it doesn't look as "ugly" as the bgcolor difference is not noticeable, I would like there to be no gap between the text starting and the top of the block/bottom of the header. Any help would be appreciated, I don't know what is causing this.
The problem can be fixed by
.sidebar1 { vertical-align:top; }
The gap has something to do with the padding on the .content article, in the sense that removing padding removes the gap, and the padding is influencing the position of sidebar because they are both table cells in the same table row, but I confess that's a bit of a woolly explanation, and I can't actually identify the specific CSS requirement that this relates to.