CSS - dynamically calculate width - css

I come across width: calc(25% - 20px + 5px);
I couldn't find any answer via google. I wanted to know how to get the width to be 410px for three boxes in each row, because right now it returns me 4 boxes in smaller width than 410px.
Any help or insight will be appreciated.

This method resolves the entire expression into a single value and then applies that to the element.
The thing you're trying to do would first calculate the 25% of the parent element as an integer value and then it would move on to the next operand. Then would calculate the result and will apply.
I think, you need to lessen down the parent element's width property. Then you'll see three checkboxes with a width of 410px.
Secondly, you can also try to make sure the expression is accurate while calculating the result for the width.
Try this fiddle: http://jsfiddle.net/afzaal_ahmad_zeeshan/D6sQ5/ To see, how calc() method works.

Related

What Is Result Of calc() In CSS

We have now started using calc() in css, for setting widths on a result of calculation.
For example:
<div id='parent'>
<div id='calcWidth'></div>
</div>
#parent{
width:100px;
}
#calcWidth{
width:calc(100% - 3px);
height:100px;
background:red;
}
I know how calc() works, but I just want to know what is returned in css, in the place of calc(100% - 3px); in the example given above.
Whats my confusion?
In the above example width:calc(100% - 3px);
say the 100% width is actually 100px, which will be determined at runtime by css.
So the calculated width will be 100px-3px=97px 97px and if you convert it to % 97% right?
But now, there are two possibilities
97px is returned, which is set as a width.
97% is returned, which is set as a width.
My Question is:
In both cases now the width shall be set to 97px, but what is
returned as a result of width:calc(100% - 3px);, 97px OR 97% ?
you can also see this fiddle:
http://jsfiddle.net/8yspnuuw/1/
EDIT: please read
See friends: Take a simple example:
<div class='parent'>
<div class='child'>
</div>
</div>
.parent{
width:200px;
}
.child{
width:20%
}
I know the width of child will become 160 px when it is rendered.
okay! but thats not what is set in css right? css sets it in %, it is
just rendered in pixels.
So similarly, using calc, does it return % or pixel
Or to explain my question, read BoltClocks answer, what is the computed value, (and not the used value, i know that is in pixels)
The spec does not define very strictly what the computed value of a calc() expression is, however it does say that percentages are never calculated as part of the computed value. How exactly this value is represented is left as an implementation detail.
If you see a pixel length instead of a percentage, then that length is the used value, not the computed value, because the pixel value can only be determined after calculating any percentages and laying out elements.
Note that getComputedStyle() may return results that are inconsistent with the CSS definition of "computed value". This is one of many unfortunate consequences of browsers doing their own thing back in the 90s.
The rendered widths are in pixels.
Whatever the pixels size of the calcWidth div is, the value 3 is reduced from it..for example if the width of parent is 200 the calcWidth div's width will be 197px. so it is px and not %
Demo
document.getElementById('calcWidth').offsetWidth;
CSS does not support dynamic values (bedides simple percentage values like width: 100%;). That means the 100% within calc() are converted one time initially to px and not continiously.
That already answers your question. The %-value gets converted into px end you end up with 97px. You can confirm that with window.getComputedStyle() or by taking a screenshot and measure it.
calc() does not have a computed value; it occurs at time of render -- that is why you can mix units.

CSS - "The sum of the horizontal components of a block-level element box always equals the width of the parent?"

I am reading CSS The Definitive Guide by Eric Meyer. On page 162, it says the following:
Almost as simple is the rule that says that the sum of the horizontal components of a block-level element box in the normal flow always equals the width of the parent.
I find a similar passage in the W3C specification:
The horizontal position and size of a non-floating, block-level element is determined by seven properties: 'margin-left', 'border-left', 'padding-left', 'width', 'padding-right', 'border-right' and 'margin-right'. The sum of these seven is always equal to the 'width' of the parent element.
However, I can think of a very simple case where the above rule does not hold true.
# HTML
<div><p>This is a paragraph.</p></div>
# CSS
div { width: 200px; }
p { width: 300px; }
Obviously I could set overflow to contain the p element. However I just want to know am I interpreting the rule incorrectly?
You shouldn't read the old specifications of CSS1, except for curiosity, as you can read in the red box on the page you linked. CSS2.1 defines well this situation: in paragraph 10.3.3 you can read that such configuration is called over-constrained, and one horizontal margin is ignored and set to a value in order to make the equality true. The right one will be choose if the writing mode is left to right, otherwise it'll be the left one.
I think it means that the "sub element at 100% always equals the width of the parent". Obviously if you set the width to anything smaller/bigger it will differ. But it inherits the same width unless specifically set.

Three Variable-Width, Equally-Spaced DIVs? What About Four?

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).

If div has a line-height of 0 and its only child, span, has line-height:0, where's the div's height coming from?

Here's my doubt. I've got a parent div with a child which is a span. Both have line-height set to 0. The span has font-size set to many many pixels (198px).
The problem: the div gets a height. But, from what, if it should come from the spans line-height, which is 0?
I set up a tinkerbin. Check it out if if you're interested.
http://tinkerbin.com/0oCT7PRf
This happens at least in firefox and chrome, so this is almost definitely a standardized behavior.
Note!
This is a css behavior doubt. I'm interested in knowing what's happening, not on "fixing" an "issue".
Thanks in advance.
The text still has a size; the letter 'F' is expanding the div to fit.
Update from the spec:
On a block container element whose content is composed of inline-level elements, 'line-height' specifies the minimal height of line boxes within the element.
http://www.w3.org/TR/CSS21/visudet.html#line-height
So the height of the box really is coming from the font-size, as the line-height is only defined as a minimum of 0, but not explicitly 0.
Yes, the is taking the height of its inner element. If you want it to correctly take its defined height/line height, you have to set it to behave as a block element ( display:block;)
Also, when hiding elements on IE using line height / height :0, IE won't collapse the element unless font-size is set to 0 as well.
The answer I've comeup with:
First facts backed by the spec:
When you have a line height greater than the font-size - what you usually see - it's pretty easy. Take the line height, subtract the font-size, divide it by 2. Apply the result to both the top and the bottom of the "glyphs box", and that's it. So if your font-size is 14px, and your line height 16px:
16px - 14px = 2px
2px / 2 = 1px
Add 1px above the "glyphs box", add 1px below it. The box gets a height of 16px, and that as expected becomes the height of the parent container (assuming, as in the case, that there's only one line-box in it).
When the line-height is less than the font-size (our case) the thing gets trickier. Lets use the same formula for a font-size of 54px and a line-height of 0.
0-154px = -154px (the spec allows a negative value here so we're alright)
-154px / 2 = -77px
So, our font has a size of 154px... and here's something else you need to know. A font has both a distance from the baseline to it's top and from the baseline to it's bottom. Pretty simple. The spec calls the first one height(A) and the second one depth(D). So A+D = distance from top to bottom.
Now here's what I think is happening in the case I presented in the question. This is what I concluded from "my fiddling" and not from the spec (since I couldn't find it there).
Let's continue with our formula.
We got -77px from dividing the result of the difference between the line-height and the font-size.
Our font-size is 154px.
Now we've got to add -77px to the top, and -77px to the bottom. Adding a negative is subtracting - so we're in fact subtracting 77px.
This is easier explained with a drawing.
So yeah, that's where I believe the height is coming from. It's at least related to it.

Fill 100% of the browser viewport programatically with a variable number of elements

I'm trying to fill 100% of the viewport in WebKit (Chrome) using maths.
What I'm doing right now is counting the number of elements and dividing that into 100 and then setting all of the widths for the elements to the resulting percentage, following the basic plan of liquid elements.
The problem is that as the number of elements gets very high, but even after the first few are added, there quickly begins to be an issue where a large amount of space opens up on the right of the elements as the browser fights between percentages, pixels, and rounding.
So my question is, how might you go about taking a variable number of elements and ensuring that the entire viewport is filled?
CSS and Javascript are both fair game, but I would prefer to avoid jQuery unless it has an incredibly simple solution. However, if you can only do it through jQuery, even if it's longer, post it anyway and I can see if I can unravel it.
I should stipulate clearly that this solution must work for a liquid layout. The browser and the containing elements must be able to resize down to about 200px. Any solution that depends on cutting apart a known quantity of pixels won't work for me.
I've published a test site if you're not sure what I mean.
display: table to the rescue!
The problem with my initial solution, of course, is that the elements are floated left and then given explicit widths. The upshot is that as the browser rounds the widths to the nearest pixel, you get jumpiness on the right-hand side of the viewport as you slowly gain and loose total pixels.
The beauty of a table is that the browser already knows that each cell should fill exactly its portion of 100% of the table's width. If the table is 100% as wide as the viewport and you have 4 cells each cell will be 25% of the viewport. Add another and the browser gives each cell as close as it can to 20% of the viewport. It handles all rounding for you so at any given time some of the cells may be a pixel bigger than other ones but the difference is always a pixel and the viewport is still filled perfectly.
The only downside I can see is that you need to have elements that you can put stuff in to be able to use display: table-cell because table cells are non-block level elements and can't be given explicit widths. They need content in order to display. Luckily for me, I can have a ul with li elements filled with a elements and thus I can hang the CSS nicely.
For the list
<ul class="mess">
<li class="mess-part"></li>
<li class="mess-part"></li>
<li class="mess-part"></li>
<li class="mess-part"></li>
</ul>
You need to apply the styles
.mess { display: table; height: 300px; width: 100%; margin: 0; padding: 0; }
.mess-part { display: table-cell; height: 100%; }
And you get a nice, pretty, 100% wide, always filled, liquid-layout spread of elements.
I've published an interactive version of the fix.
Pretty neat, eh?
HT to this question for getting the gears in my head turning.
Maybe because for example 5.4% is rounded to bottom, so if you got 10 elements, which all miss 0.4% you are missing 4% of the page, so if you got 20 elements, your missing 8% and so on. Maybe if you Math.ceil 1 element and Math.floor the next one. You will have less white space on the right side. Because you then only miss 0.2% each 2 elements. But still generating a white space.
What is the best solution is to not use % but us PX. Because those are round to PX instead of % which is a lot more. But then still you can use Math.ceil and Math.floor to fix the floating point numbers and have no white spaces anymore.

Resources