I am trying to create a horizontal menu with the elements represented by <span>'s. The menu itself (parent <div>) has a fixed width, but the elements number is always different.
I would like to have child <span>'s of the same width, independently of how many of them are there.
What I've done so far: added a float: left; style for every span and specified its percentage width (percents are more or less fine, as the server knows at the time of the page generation, how many menu items are there and could divide 100% by this number). This works, except for the case when we have a division remainder (like for 3 elements), in this case I have a one-pixel hole to the right of the parent <div>, and if I rounding the percents up, the last menu element is wrapped. I also don't really like style generation on the fly, but if there's no other solution, it's fine.
What else could I try?
It seems like this is a very common problem, however googling for "child elements of the same width" didn't help.
You might try a table with a fixed table layout. It should calculate the column widths without concerning itself with the cell contents.
table.ClassName {
table-layout: fixed
}
If you have a fixed width container, then you are losing some of the effectiveness of a percentage width child span.
For your case of 33% you could add a class to the first and every 4th child span to set the correct width as necessary.
<div>
<span class="first-in-row">/<span><span></span><span></span><span class="first-in-row"><span></span><span></span>...
</div>
where
.first-in-row { width:auto; /* or */ width:XXX px; }
have you tried the decimal values, like setting width to 33.33%?
As specified in the CSS syntax, the width property (http://www.w3.org/TR/CSS21/visudet.html#the-width-property) can be given as <percentage> (http://www.w3.org/TR/CSS21/syndata.html#value-def-percentage), which is stated to be a <number>.
As said at the number definition (http://www.w3.org/TR/CSS21/syndata.html#value-def-number), there some value types that must be integers, and are stated as <integer>, and the others are real numbers, stated as <number>. The percentage is defined as <number>, not as <integer> so it might work.
It will depend on the browser's ability to solve this situation if it can't divide the parent's box by 3 without remaining, will it draw a 1- or 2-pixel space, or make 1 or 2 spans out of three wider than the rest.
In reference to Xian's answer, there's also the :first-child pseudo-element. Rather than having first-in-row class, you'd have this.
span:first-child {
width: auto;
}
Obviously, this is only applicable to a single line menu.
Related
I am reading the book Head First HTML and CSS and there it is written that a requirement for any floating element is that it must have a width. I tried floating right a div element without specifying width on it, and the float property works(it moves the div furthest right as possible) as supposed. Does this mean that there is an error in the book, or it is something that i am missing ?
Yes, you can have floated elements with no width values declared in the cascade. Then, through a defaulting process, the specified value will be the initial value.
For width, the initial value is auto.
CSS explains what should happen when a floated non-replaced element has width: auto:
If width is computed as auto, the used value is the
"shrink-to-fit" width.
Calculation of the shrink-to-fit width is similar to calculating the
width of a table cell using the automatic table layout algorithm.
Roughly: calculate the preferred width by formatting the content
without breaking lines other than where explicit line breaks occur,
and also calculate the preferred minimum width, e.g., by trying all
possible line breaks. CSS 2.1 does not define the exact algorithm.
Thirdly, find the available width: in this case, this is the width of
the containing block minus the used values of margin-left,
border-left-width, padding-left, padding-right,
border-right-width, margin-right, and the widths of any relevant
scroll bars.
Then the shrink-to-fit width is:
min(max(preferred minimum width, available width), preferred width)
The "shrink-to-fit" algorithm is now called fit-content measure.
float:right is simple stacking of elements, left to right until a line width is filled, then top to bottom. Like writing an English newspaper page.
float:left is used for things like a sidebar, it would take up the whole page, unless its width is constrained. This is why the width must be specified.
I have a grid of flippable cards with variable content and try to set the height of cards with less content to the same value as the card with the maximum content. But no matter to which box/cell I apply height:100%, the smaller cells stay just as large as they need to. I can see that the row itself naturally has the maximum height, but why can't all child cells inherit that height?
Here is the example: http://www.bootply.com/NnHFEKwrwu
To understand height, this will only take up the specified height that is applied, meaning that if your container element has a height of 300px, and that child element therefore has the CSS height:100%, THEN that child element will take on that height.
In your case, you really haven't specified a height on any of the elements, only height:100% and min-height:100%. More than likely, your min-height will always be a set number, meaning px, em, etc.
What I'm assuming you want is to have ALL the boxes the same height. If this is the case, then you can see a previous answer that I posted here. The objective is to get all XX elements (that you want to group), and determine the max-height of the group. We then apply this height to all the elements in the group.
This happens a lot when you want carousels, modals, tooltips, or in your case, columns, to be the same height throughout, and therefore making your layout look a lot nicer.
In your case, you'd want to iterate through all the .card elements and get the max-height of those, then apply it to the group. I like to use outerHeight() b/c this will get the border, padding, and margin as well.
var maxHeightOfCards = $('.card').map(function() {
return $(this).outerHeight();
}).get();
// or use $('.card').css('height', Math.max.apply(null, maxHeightOfCards))
$('.card').height(Math.max.apply(null, maxHeightOfCards));
...although there are many things wrong in your code, the solution you are looking for is easier than you think:
.row {
display:tab
}
.row > div {
display:table-cell;
float:none;
height:100%;
}
It's as simple as it gets. Then you can use height:100% to the children elements.
<div style = "float : left; background-color: #dd3fb8;">
<a style = "margin-left : 10%;">a</a>
<a>b</a>
<a>c</a>
</div>
In the example above, the letter "c" would be on new line, but if I set "margin-left" to px unit, "c" would be on the same line as "a" and "b". Why does this happen?
Unfortunately, the CSS2.1 spec doesn't appear to have a clear answer to this. In fact, I would say this is well within the realm of undefined behavior.
Here are the relevant points I can find:
Floats without a specified width will shrink to fit their contents. In the case of floats with only inline content, the float needs to be made just wide enough to fit its contents on a single line (notwithstanding explicit line breaks) and no more.
Percentage margins are calculated based on the width of the containing block.
Note that it says:
If the containing block's width depends on this element, then the resulting layout is undefined in CSS 2.1.
... but as far as I can see, the behavior is consistent across all browsers.
That being said, the reason this statement applies is because since the margin of the inline element falls within the content bounds of the float, it can be said that the width of the float (the containing block of the inline elements) depends on the this element (the element having the margin).
Here's what I can deduce based on the points above:
When the margin is specified as a percentage, the width of the float is calculated without taking the margin into account, because it's not possible to calculate the margin until the width of the float has been determined.
The margin is then calculated based on the used width of the float, and the letter "c" wraps to a new line as a result of being pushed forward by the margin on "a". The width of the float does not change.
Again, none of this behavior is specified at all, and so technically it's not in violation of the spec. However, it seems sensible.
When the margin is specified as a pixel value, the margin is calculated first. The width of the float is then calculated taking this margin into account (remember that horizontal margins do apply to inline elements as normal). Per the shrink-to-fit algorithm, this is the preferred width: just wide enough to contain all the inline elements on a single line.
Unlike with percentage margins, this is very clear-cut, as implementations should have no trouble calculating computing absolute values for margins first.
I would be hard-pressed to call this a bug in any of the browsers, especially since they all behave consistently.
Lastly, of course, you can avoid this undefined behavior entirely simply by giving your floats explicit widths where possible. It does help to understand why you should do so, however.
Since your div is floated, and its width is auto (implicitly), http://www.w3.org/TR/CSS21/visudet.html#float-width applies:
If 'width' is computed as 'auto', the used value is the "shrink-to-fit" width.
“shrink-to-fit” width basically means, let the element be as wide as its content requires it to be.
Now without the margin-left, that is no problem: All three of your a elements are inline elements that contain a specific character each – easy enough to determine their individual widths, and add them up.
But now you want a margin-left in percent, and here things get complicated – if we look at the definition for margin-left, it says:
Percentages: refer to width of containing block
Now, that leaves us in a bit of a pickle, since the width of the containing block (which is established by the floated div element), is computed based on its content – but now this margin-left would change the overall width of that content, but is in itself dependent on the width of the containing block, which it itself influences …
That’s a classical problem of two measurements that are dependent on each other … and that is therefor basically unsolveable.
http://www.w3.org/TR/CSS21/box.html#margin-properties says,
The percentage is calculated with respect to the width of the generated box's containing block. […]
If the containing block's width depends on this element, then the resulting layout is undefined in CSS 2.1.
Edit: Basically the same as what BoltClock said in his answer, just took me a little longer …
The link has a left margin of 10%, 10% of how much? The parent element is floated left which means it does not have a width of its own, instead it expands as much as its contents. If you try to imitate how the browser would compute the resulting box and you will find yourself in a fix:
Let the width of the content (and therefore the container) be 30px
Add 10% of 30px = 3px left margin to the link
The resulting width of the container is 30 + 3 = 33px
This creates a loop where margin increases as outer width is increased and outer width increases as the margin is increased (10% of 33px = 3.3px means container width changes from 33px to 33.3px and so forth). For such computations the resulting behavior is undefined (as pointed out by CBroe).
The browser seems to avoid the loop and sticks with the 30px width. The 3px margin introduced after calculation causes the third link to flow into second row. The browser again avoids the loop by sticking with 30px width.
Look at this fiddle: http://jsfiddle.net/guard/UtpGm/
The w is a wrapper, having both min- and max-width.
The title inside it has a long text inside.
As far as I understand the following happens
the wrapper span/div/whatever (tried both div and span with both block and inline-block display mode) first tries to occupy as much width as it can, and calculates the width sufficient to have the title on a single line (for the sample its 483px)
then the width is compared to the min amd max widths specified, and adjusted - in this case its decreased down to 380px
As a result there's unused space inside of the wrapper.
How can I make it occupy "as few space as possible" for the content to fit (to look the same, but without the unused space), given both the min and max width constraints? In the sample case the proper width is 312px.
Note: I can do really anything with the wrapper. It can be positioned absolutely or relatively, it can be child of any other element, any additional wrappers can be added.
Here's the first solution that comes to my mind that works:
$('#w').css({"width": $('#title').width()});
The fiddle: http://jsfiddle.net/UtpGm/9/
Of course, one would prefer a pure-CSS approach, so I would love to see other answers.
There is no such kind of width calculation in CSS.
The only thing that is close enough in CSS for the moment is to use display:table-cell :
http://jsfiddle.net/UtpGm/13/
When you define table-cell its width:auto value is resolved to
width:max-content-width. Here max-content-width is an internal value that equals to intrinsic max width of the content.
For <p> element its intrinsic max width will be equal to the width of its text when it is replaced in single line. And if <p> has <br>s inside - to longest line.
for some reason this worked:
#w {
border: 1px solid red;
min-width: 10px;
max-width:380px
width: auto !important;
display: inline-block;
}
#title{ max-width:380px; display: inline-block;}
Also bear in mind that some of your sample text ie"longlonglonglong" counts as one word because there are no spaces, so it will automatically jump down to the next line if it can't fit on that line and cause a white-space in the span.
Hope this helps, cheers
I'm trying to make a box with rounded corners where the height and width of the div depends on the content, so it's automatically adjust to it...
You can see the example here: http://pastehtml.com/view/1duizyf.html
The problem is that i can't get the "test_mid_left" (black background) and "test_mid_right" (turquoise background) to inherit the height from the "test_mid_center" (green background). I have tried height: 100% and auto, but none of thoose work. So how do I get them to inherit the height from the content?
(The reason why I have used "min-height: xx" in the left and right content on the example is just to show which boxes I am talking about)
As already mentioned this can't be done with floats, they can't inherit heights, they're unaware of their siblings so for example the side two floats don't know the height of the centre content, so they can't inherit from anything.
Usually inherited height has to come from either an element which has an explicit height or if height: 100%; has been passed down through the display tree to it.. The only thing I'm aware of that passes on height which hasn't come from top of the "tree" is an absolutely positioned element - so you could for example absolutely position all the top right bottom left sides and corners (you know the height and width of the corners anyway) And as you seem to know the widths (of left/right borders) and heights of top/bottom) borders, and the widths of the top/bottom centers, are easy at 100% - the only thing that needs calculating is the height of the right/left sides if the content grows -
This you can do, even without using all four positioning co-ordinates which IE6 /7 doesn't support
I've put up an example based on what you gave, it does rely on a fixed width (your frame), but I think it could work with a flexible width too? the uses of this could be cool for those fancy image borders we can't get support for until multiple background images or image borders become fully available.. who knows, I was playing, so just sticking it out there!
proof of concept example is here
The Problem
When an element is floated, its parent no longer contains it because the float is removed from the flow. The floated element is out of the natural flow, so all block elements will render as if the floated element is not even there, so a parent container will not fully expand to hold the floated child element.
Take a look at the following article to get a better idea of how the CSS Float property works:
The Mystery Of The CSS Float Property
A Potential Solution
Now, I think the following article resembles what you're trying to do. Take a look at it and see if you can solve your problem.
Equal Height Columns with Cross-Browser CSS
I hope this helps.
The negative margin trick:
http://pastehtml.com/view/1dujbt3.html
Not elegant, I suppose, but it works in some cases.
You need to take out a float: left; property... because when you use float the parent div do not grub the height of it's children... If you want the parent dive to get the children height you need to give to the parent div a css property overflow:hidden;
But to solve your problem you can use display: table-cell; instead of float... it will automatically scale the div height to its parent height...
Most of the times, the Previous parent has a heigt manually set, so you can use that value as reference, no other dirty tricks will be needed, and if the number is not the same for any reason maybe a comment can be added with the original number so in case you need to change it, by searching at the all the values, this one can be adjusted or even changed, in the time someone resolve this one for us.