CSS: How to Apply Variable Widths Depending On Number of Siblings - css

I have a container element that might include either one or two sibling children. When there is only one child, I want it to be 100% the width of the parent. When there are two children, I want each to be 50% of the width of the parent. (And if I had three, I'd like each to be 33% width, etc.)
Is there a way to accomplish this with a pure CSS solution, or would I have to use Javascript to detect the number of elements, and style them accordingly?
The DOM structure could look like this:
<div class="container">
<div class="element1"></div>
</div>
or like this:
<div class="container">
<div class="element1"></div>
<div class="element2"></div>
</div>
Here is a fiddle to experiment on: http://jsfiddle.net/Mx3ae/

The approach to this question depends on what browsers you have to support. If you need to support older browsers, you may need a hack like display: table-cell, or a javascript approach. Either way, it's harder than it should be.
But if you can use modern, evergreen browsers, the new CSS Flexbox specification makes this problem trivial. To use it in this case, you'd simply set display: flex; on the .container element. Then, because you want the internal elements to expand to consume any available space, you'd use the flex-grow property. In my example, I've set flex-grow: 1; so that they all take up the same amount of the remaining space, but you can use various values so that they vary in how much of the remaining space they consume. See the fiddle.
That's just the beginning with Flexbox. You can allocate space dynamically, re-order display of your elements, and much more. I recommend Chris Coyier's 'Complete Guide to Flexbox' as your daily reference, although you may want to search for some tutorials as well.
EDIT: I shouldn't necessarily call display: table-cell a hack. It actually works pretty well, and is a use that the spec intends. Do try it if you need to dynamically allocate space for older browsers, or even if Flexbox doesn't give you quite what you want.

Related

Why bootstrap uses floating elements to construct Grid System? [duplicate]

I was tinkering with custom grid and wanted to see how other people have created their grid-systems. Since twitter's bootstrap seemed to be so popular i've looked at its code. Now i wonder why are they using floats? I would use display: inline-block; html elements have either display: inline; or display: block; i would try to avoid floats. But for some reason bootstrap creators decided to use floats. first i was thinking they used them to have backward compatibility since ie6 does not support display: inline-block; and ie7 supports it only on elements with display: inline; by default. But ie6 more or less out of the game and since they use micro clearfix hack which uses *zoom: 1; to target ie6+ IMO they could replicate the same display: inline-block; with *display: inline; *zoom: 1; So the final Question Why Floats Over Display Inline Block? Are there any issues they tried to solve i didn't mentioned above?
Inline blocks are white-space aware, have an auto width of the actual content and stacks in the order they have in HTML. Floats aren't but require a clearfix method and are based on block elements. These elements have auto width on the available space horizontally. Purely semantically, inline-blocks are less semantic since the white-space aware format and importance of order. But looking at it purely in a functional way, both just aren't made for a grid. And if it wasn't for pseudo CSS, we would have un-semantic HTML tag clearfixe's as well. So in my believes they are both not winners. But there is no alternative for the time being when flexbox will become mandatory in upcoming years.
With inline blocks:
<div>
<div style="display:inline-block; width:30%;">col1
</div><div style="display:inline-block; width:70%;">col2</div>
</div>
Tags must be glued together/appended, to dismiss any gutter. The container div is necessary to force the items being part of a separate row.
With floats:
<div class="clearfix">
<div style="float:left; width:30%;">col1</div>
<div style="float:left; width:70%;">col2</div>
</div>
Clearfix is necessary to force a "row" (dismiss any normal flow items issues or floats after the floats)
Whether use one or the other is a matter of your goal (and taste). I must say I like inline-blocks more than floats, as long as you know the both of the col widths or use relative sizing (%). I thinks it's more intuitive and predictable than floats with clearfix, a fix" for issues that aren't even issues if it was used by how it should be used. Only the white-space awareness of inline blocks force you to use some funky html, that's a downside.
Ironically, tables do exactly all this (and even col-heights and vertically alignement's) without any issues. Since inline-blocks have to be placed in order, there's an motive for discussing here.
If we are talking about responsive, table 'loses' of inline-blocks. Let say you have 4 cols on a desktop and you want 2 cols on a tablet and 1 on a mobile. With inline blocks, you 'just' give the cols other width dimensions and they hopefully wrap nice (be aware of margins as they collapse). With tables, you're bound to actual rows, which can be quite stubborn. Flexbox is needed for a long time and looks beautiful. You can adjust the layout flexible on certain circumstances.
Bootstrap can be handy to learn how they did something. Just read in 3.0 they are using relative grid sizing. Which gives an issue with nested grids and aligning.
---- --a- ---- ----
---b------
.... ..c.
Col a is a normal parent col. Col c is a child nested col of b. It's hard to align c with a with relative sizing since the gutter is variable to the container, unless you're using padding and border-box model. But that way you lose a lot of flexibility. When you want the col to have some background and padding, you're messing up the grid system, so you have to use container which you style, which would clutter the code. I haven't studied if they found a solution to this. I haven't yet. I went to fixed pixels, but that means in responsive design you can only have a few fixed width's and for everything around mobile use a relative grid.
I prefer grid systems that use display: inline-block; rather than float, such as Pure (formerly Yahoo YUI Grid), because they internationalise without extra styles; change the text direction to right-to-left and the layout automatically reverses; floats don't do this. Floats also introduce the need to clear and other cross browser oddities. Any inaccuracies that inline-block may have over float can be remedied, as demonstrated by Pure. As to the criticism that display: inline-block; is not meant to be used for layout, perhaps the use of display: table; should also be banned for cross-browser centring. I would also question whether the term Semantic Web really applies to CSS since the term is primarily concerned with HTML and using its elements and attributes to impart machine readable meaning; the whole point of CSS is to style semantic HTML as radically as one wants to, hence classic sites like CSS Zen Garden.
I say that as long as the technique is not exploiting a bug, is not obstructing content to users and devices and is sufficiently supported then it is acceptable. There is no reason that one can't use CSS in unorthodox, but supported, ways, just like Stu Nicholls' CSSPlay.
Interestingly, Flexible Box is also incorporated into Pure grids, a superior layout system compatible with modern browsers (≥IE10 and equivalent browsers).
In the term of semantic web, the display: inline-block should be used when we want to place a block level element like <img> within line(s) of text. We shouldn't use inline placement for making the pages main layout. The element with display: inline-block also takes effect from properties like font-size and line-height of parent element. This will decrease the accuracy of page layout.
You would better get in the habit of using float instead of inline-block when making the page main layout.

Advantages of using display:inline-block vs float:left in CSS

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.

Calculating width as percentage minus margin with LESS CSS

I use the Twitter Bootstrap grid system in my CMS app.
When users built a page, they can add any number of columns to a row. Consider this row:
<div class="span9 row">
<div class="span5">span5</div>
<div class="span4">span4</div>
</div>
What I want to do, is add a feature where users can set a row to equally distribute its width among the columns within.
So the span5 and span4 classes will be overridden. This would essentially behave like a table row, but I think it's hacky to make the row display: table-row, and it would probably ruin the responsive features of the TwBootstrap grid.
What I would like to avoid, is to define each combination of width as such:
<div class="span9 row shared child-count-2">
<div class="span5">span5</div>
<div class="span4">span4</div>
</div>
And in CSS:
.row.span9.shared.child-count-2 > div {
width: 340px;
}
Since I'm already using LESS for CSS, I thought there might be a handy calculation that can make this work.
The problem is that specifying 50% width doesn't take into account the 20px of margin-left. So I need to take the width of the row, minus 20px for each column. And then divide the remaining width with the number of columns.
Also, I would like to avoid using JavaScript. I don't like rendering 99% of a view, and then doing adjustments in script. If script execution gets a tiny delay users will see the layout flickering around. Not good.
So, is there any way to do this from LESS/CSS?
You can achive that using LESS. With LESS you can use evaluation of JavaScript expressions wrapping them into back-ticks:
#var: `"hello".toUpperCase() + '!'`;
So you can use also things like document.getElementById('myId').width to get the width of an element and so on.. Check here lesscss.org and go to "JavaScript Evaluation" section.
If you need more help, just ask! :)

How to force div width with CSS to stretch to its content but not to be restricted by its container?

I'm trying to make a HTML "showcase". I am thinking of using elements like this:
<div id="index-showcase-tabs">
<div id="index-showcase-tabslide">
<div class="index-showcase-tab" id="showcase-tab-1">Item1</div>
<div class="index-showcase-tab" id="showcase-tab-2">Item2</div>
...
<div class="index-showcase-tab" id="showcase-tab-N">ItemN</div>
</div>
</div>
The showcase items are floated left, and I don't know their precise width, nor the number of them.
Problem is: if the combined width of the items is bigger than the container (index-showcase-tabs), I don't want them to break line (which they do by default). I want them in one line, and I want to hide the overflow and then let the user scroll them with javascript (not by scrollbar...).
How would I do that?
PS: There's not much css for the items yet. I only gave the slider a specific heigth:
#index-showcase-tabslide
{
height: 34px;
}
Edit: Here you can see my problem.
Edit2: explaining more with a fiddle: http://jsfiddle.net/TbSfj/19/
For this, you cannot use float: left. Instead use display: inline - this will have the same effect for what you want to accomplish, and it will not be constrained to the parent div in the DOM model.
check out this sexy control:
http://jsfiddle.net/SoonDead/U6QdQ/20/
this way made for my project, but I think it does what you want.
The tricks are:
Because you use a lot of characters that can "linebreak" and even forcefully disable linebreaks have different results in 1-2 browsers, I would recommend against it.
Instead make the overflowing width wide enough to hold all the elements easily, so if javascript is disabled it will not look ugly.
(I know that you are fine with jquery, so I use it within the example, also the outerWidth property in simple js has bugs in webkit (tends to be 0 in some cases).)
So you need to sum up the elements' outerWidth() and set the content holder's width, so you can use scrollLeft, and not overscroll.
There is no other trick, just a scrollTo function because calculating positions are not that trivial if you are new to jquery and you might want to use that.

What’s the point of the ::before and ::after pseudo-element selectors in CSS?

I have used CSS pseudo-element selectors like many others, mainly just to say I've used them.
But I am racking my brain and struggling to come up with a reason for their place alongside markup.
Take the following example:
<p>Hello</p>
p::after {
content: "*";
}
What is the advantage of using this over using <span> tags?
Am I missing the point of ::before and ::after? Is there some rock solid reason for using them over pre-existing semantic markup?
The CSS2.1 spec says this about generated content:
In some cases, authors may want user agents to render content that does not come from the document tree. One familiar example of this is a numbered list; the author does not want to list the numbers explicitly, he or she wants the user agent to generate them automatically. Similarly, authors may want the user agent to insert the word "Figure" before the caption of a figure, or "Chapter 7" before the seventh chapter title. For audio or braille in particular, user agents should be able to insert these strings.
Basically the purpose is to minimize pollution of the content structure by "content" that is otherwise more suited as presentational elements, or better to be automated.
If you're talking about :before and :after: They're used as presentational elements for cases where adding more elements into the actual document would be mixing structure with appearance. A few cases I've seen:
Bullets in bulleted lists
Quotes around q elements
Stylish shadows
Decorations and the beginning or end of text
These particular pseudo-elements are designed to add “content” that’s actually just a visual aid.
The prime example is adding quote marks around the <q> element, which Firefox does using these selectors in its default stylesheet. Some people also use them to clear floats.
You shouldn’t use them for actual content, despite the name of the CSS content property, as non-visual user-agents (i.e. screen readers) should ignore them.
I’ve never come up with much use for them, although I did once use them to add little Unicode icons to hovered links on a personal site — like you, pretty much just to say I’d used them.
Honestly, the only worthwhile useage is to force elements to have the correct size in the dom. Use this code for example:
<div class="container">
<div>this div is floated left</div>
<div>this div is floated left</div>
</div>
Typically you would have to specify an exact or min height for the .container div. if you were to apply ":after" with some very simple css, any background you applied to the .container would actually show up (in almost every browser) properly, with few to no shims.
.container:after{
content:'.';
height:0;
line-height:0;
display:block;
float:left;
visibility:hidden;
}
Now try that example, applying a background color or image, and you'll see that the .container div always has the appropriate height (which would be the total combined height of the inner contents) even if all the inner html is floated (as is the case in most ul/li css buttons).
I also use an after on every div that I wrap all my content in per html page. This is due to the possibility that all of the content on a given page could be floated, and I want to make sure that my content div always has the correct size/padding with the appropriate background.
CSS3 Pseudo Selectors also include essential ones like :link, :hover, :active, :focus, :first-child, :nth-child. It's impossible to make a useful site without most of these.
As for the less commonly used pseudo-selectors like :after and :before, they're useful in certain cases where the content is dynamically generated and you want to insert something before a specific element or tag.

Resources