Margin messing up percentage based width - css

I have a <ul> inside of a width: 100%; container.
Each <li> has width: 25%;.
I want to have a margin-left on the li elements, but this screws up the width %.
Here is the fiddle showing the issue: http://jsfiddle.net/u3hTW/
To 'correct the issue, I can apply box-sizing to the li elements and use padding instead of margin, but the 'kicker' is that I want the nth-child(1) to have no margin or padding which causes it it to look different from the rest of the li elements.
Here is a fiddle showing that: http://jsfiddle.net/u3hTW/1/
I am wondering if there is a better way to be approaching this. The goal is to maintain a % based width, with space between all but the first child.

I would suggest using a % for your width, and for your margins.
.list li {
float: left;
width: 23%;
margin-left: 2.66%;
}
.list li:nth-child(1) {
margin-left: 0%;
}
FIDDLE showing that approach
In general to get spacing between containers I prefer margin, because later you may need inner padding for something else, or run into cross-browser box-sizing issues with padding.

The thing is, you're already using your 100% by 4x25% width of each li element. So when you add the margin, the last one will 'jump', because < 25% of the container div remains.
What you can do is:
Make your li's a little smaller, like 23% or so, and use percentage for your margins. A little calculations is required to make sure everything is spaced apart evenly.
Use flexbox (please check if browsersupport meets your requirements)
A compleet guide to this relatively new css boxmodel can be viewed here, as done by Chris Coyier: http://css-tricks.com/snippets/css/a-guide-to-flexbox/

This is the formula to calculate the width of the columns with the method suggested by cjspurgeon:
w = 100 - 2mc
---------
c
Where:
w = width of the column
m = margin expressed in %
c = number of columns
The constant 100 = 100%, or total width of columns + margins. The constant 2 is the two margins considered (left and right)
So, say you want 6 columns with a margin of 1.7% left and right:
w = (100 - 2(1.7 * 6)) / 6
w = 13.2666%
Your selector would look like this:
.column {
width: 13.2666%;
margin: 1.7%;
float: left;
/* whatever else is required */
}

Related

What's the simplest solution to make four equally sized boxes that is displayed horizontally and centered in a screen responsively?

What's the simplest solution to make four equally sized boxes that is displayed inline (horizontally) and is centered in the screen all through out responsively?
I have four divs with same sizes, displayed inline and is always placed in center, meaning they always have an equal margins on left and write of the screen. And i want it to be responsive. I already tried flex-box but i'm having trouble with browser compatibility with css3.
I don't know if this is the absolute "best" way. But something like this would definitely work.
div {
width: 22%; //adjust as necessary
margin-right: 4%; //adjust as necessary
float: left;
height: 5em; //adjust or remove as necessary
}
div.last { //alternatively you could consider using the :last-child selector
margin-right: 0;
float: right;
}
You will have to apply a class of "last" to the last div. Alternatively you could use div:last-child if they were all contained in a parent element.
Also, when adjusting the margin/width make sure they stay relative. widthx4 + margin-rightx3 should always = 100 (assuming no padding or borders).

fluid-fluid-fluid three columns

Is it possible to have 3 columns, all equal in width with 2 columns in between, all be fluid? Everything I can find shows one column fixed, or they have different width. I need them all to be the same. No matter what I do on this page, the last li doesn't come all the way to the edge of the container. If I enlarge the % of the li then it doesn't fit in smaller resolutions. Thanks!
Page example is here
CSS is here
It looks like you already got an answer on how to get it working, but you'll quickly run into another problem if you're going to have any sort of margin or border on these columns.
Those width percentages? They don't include border/margin - so if you add either of those, you'll once again have columns overflow.
Solution? Make sure to set box-sizing: border-box; - if you haven't heard of it before, Google it. It's magical!
your question puzzles me a bit. On the one hand, this example shows what you sound like you're asking for:
http://jsfiddle.net/JuamW/
On the other hand, the actual example of your site shows a fixed-width situation where your columns have no requirement to be fluid. If the above example doesn't give you what you need, could you provide some more context?
I would say it's all about calculating the right percentages.
To start fresh, remove the borders and margins on all three columns. Then make their widths 33.3333% so they will all fit perfectly inside their container.
Looking at your CSS I can see you have a margin (left and right) of 3.75% on the middle column, so you must re-calculate your column widths to 100 - (3.75 * 2) / 3 = 30.833333%.
Secondly, switch your border to an outline to prevent unnecessary width being added to your layout.
Lastly make your imgs 100% width so they fit inside their containers nicely.
Should be done after that, I used Firebug to perform all those changes on your site and it looks like it worked out.
If you want to bring the last li out add:
#categories-wrapper ul li.students{
float: right;
}
#categories-wrapper ul li.fine-art{
float:left;
}
replace categories-wrapper ul li:nth-child(2) with:
#categories-wrapper ul li.gd {
margin-left: 4.25%; /* 36px / 960px */
float: left;
}
And modify this:
#categories-wrapper ul li {
width: 30.20833%; /* 290 / 960 */
border: 1px solid #333;
position: relative;
}
Is that what you're looking for?

CSS3 box-sizing: margin-box; Why not?

Why don't we have box-sizing: margin-box;? Usually when we put box-sizing: border-box; in our style sheets we really mean the former.
Example:
Let's say I have a 2 column page layout. Both columns have a width of 50%, but they look kind of ugly because there's no gutter (gap in the middle); Below is the CSS:
.col2 {
width: 50%;
float: left;
}
To apply a gutter you might think we could just set a right margin on the first of the 2 columns; something like this:
.col2:first-child {
margin-right: 24px;
}
But this would make the second column wrap onto a new line, because the following is true:
50% + 50% + 24px > 100%
box-sizing: margin-box; would solve this issue by including margin in the calculated width of the element. I would find this very useful if not more useful than box-sizing: border-box;.
Couldn't you use width: calc(50% - 24px); for your cols? Then set your margins.
I think we could have a box-sizing: margin-box. The css box model shows exactly, what are the positions of the margins of the frames.
There are minor problems - for example, the margin boxes can overlap - but they aren't hard to solve.
I think, the situation is the same, as we can see with the overflow-x & overflow-y combinations, with the absolut positionied divs in table-cells, with the combination of min|max-width|height with the box-sizing, and so on.
There are features, really simple features, which the browser developers simply doesn't develop.
IMHO, box-sizing: margin-box were a very useful feature. Another useful feature were the box-sizing: padding-box, it exists at least in the standard, but it wasn't implemented in any of the major browsers. Not even in the newest chrome!
Note: #Oriol 's comment: Firefox did implement box-sizing: padding-box. But others didn't, and it was removed from the spec. Firefox will remove it in version 50. Sad.
The guy at the top is asking about adding margin to the overall width, including padding and border. The thing is, margin is applied outside the box and padding and border aren't, when using border-box.
I have tried to achieve the border-margin idea. What I have found is that if using margin you can either add a class of .last to the last item (with margin, then apply a margin of zero, or use :last-child/:last-of-type). Or add equal margins all the way around (similar to the padding version above).
See examples here: http://codepen.io/mofeenster/pen/Anidc
border-box calculates the width of the element + its padding + its border as the total width. So if you have 2 divs which are 50% wide, they will be adjacent. If you add 8px padding to them, then you will have a gutter of 16px. Combine that with a wrapping element - which also has padding of 8px - you will have a nicely laid out grid with equal gutters all the way around.
See this example here: http://codepen.io/mofeenster/pen/vGgje
The latter is my favourite method.
I'm sure all of this is obvious, but I'll type it out anyway because...well, I need the exercise. Would the following outcome not be just as efficient as box-sizing: margin-box;:
.col2 {
width: 45%;
height: 90%;
margin: 5% 2.5%;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
float: left;
}
http://jsfiddle.net/Fg3hg/
box-sizing is used to control from which point the padding and border are assessed to the overall size of the element. So while it's not kosher to include px margins with a % width (as is usually always the case), it's easier to calculate what the relative percentage amount should be because you don't have to incorporate padding and borders to the defined width.
This is because the box-sizing attribute refers to the size of an element after computing the given dimension-specific values (padding, borders). "box-sizing: border-box" sets the height/width of an element and takes into consideration the padding as well as the border width. The scope of an element's margin is greater than the element itself, meaning it modifies the flow of the page and its surrounding elements, therefore directly altering the way the element fits within its parent relative to its sibling elements. Ultimately a "margin-box" attribute value would cause major problems and is essentially the same as setting the elements height/width directly.
Dimensions of block-level, non-replaced elements in normal flow must satisfy
margin-left + border-left-width + padding-left + width + padding-right + border-right-width + margin-right = width of containing block
When over-constrained, browsers must adjust either the left or right margin.
I think that means the width of the margin box must equal the width of the containing block (i.e. 100%).
For your case, transparent borders with box-sizing: border-box can work much like margins.
On Codrops there are a couple of good articles on the subject of the effect of margins and row's forced to overflow. They suggest using the rem or em unit with a normalizer css setting font size to 100% for all browsers, then when you set widths and margins it is easy to keep track of the effect on the row's width by simply making a note in comments for the total width. A conversion of 16px to 1 em is the way to calculte the targeted viewports total witdh.
Working like that for the dev stage at least and then if you want 'responsive' templates you can convert widths to % including the margin widths.
The other and often simpler way they suggest to handle gutters is to use the pseudo after and the content: ''; on each of your columns which I find works really well. If you set a div class that is the defined last column such as end you can then target that class not to have the pseudo after, or to have a wider one; which ever best suits your layout.
The added bonus of using this pseudo element method is it also gives you a target for shadows that can give a more 3d effect and greater depth to the flat image on the readers monitor as well. I am experimenting with this effect at the moment by scaling up the effects being used on buttons, 'tweaking' the gradients, and the z-index.
Perhaps set the border to 0% opacity using RGBA and use the border as a margin.
There interesting situation when using box-sizing inside body content
no content no border box gives no any value on left-right margin % recount of this two box recount algoritms
.body{
box-sizing: border-box;
margin:0 3%;
}
Firefox versions before 57 also supported the padding-box value for
box-sizing, though this value was been removed from the specification
and later versions of the browser.
So margin-box even not planned...
There should be a box-sizing: margin-box;
But does the following work:
Put a div around it with
.divX{
width: XX%;
display:flex;
align-items: center;
justify-content: center;
}

CSS Table width - 100% + minus margin

I've stumbled across an issue that I'm not entirely sure how to resolve.
I have a page with a number of divs, one of which contains a table but has a margin of 20px. I need this table to 'butt' against the right-hand side of another div, which I have accomplished by using a margin of -20px - works as I'd hoped. As this div (which covers the entire right-hand side of the page) is fluid, the table has a width of 100%.
Whilst the left-hand side of the table is where I want it, the right-hand side is now 20px short of everything else.
Is there a way I can keep the negative margin on the right, without it also moving the table 20px from the right? I've tried a few things without success. My table CSS is pasted below.
.pricetable {
width:100%;
margin-left: -20px;
padding: 5px;
}
My solution was to wrap the table inside a div with the negative margin.
<div style="margin-right:-20px">
<table style="width:100%">
...
</table>
</div>
You can also set the width to less than 100% and set margin auto:
.pricetable {
width:90%;
margin: auto;
}
Hope it helps.
it is now possible with CSS calc:
.pricetable {
width: calc(100% - 20px);
margin-left: -20px;
padding: 5px;
}
You could absolutely position your table, so that it's aligned at the right.
position: absolute;
right: 0;
There's no way to add a left margin without moving the table, because the table offset is calculated in this way: margin + padding + width = offset width.
When you set the width to be 100%, the margin and padding cause the element to expand.
Padding (left) X, (right) y + width = over 100%
over 100% + negative width (X+y) = 100%.
The first definition adds some padding at each side of the table. The second definition shifts the table to the left, because it's a negative margin.
try giving table-layout:fixed and see

CSS overflow : list in a div

I have an image gallery and I dont want give an extra class to third list item:
<div class="row">
<ul class="rowUl">
<li>ssss</li>
<li>ssss</li>
<li>ssss</li>
</ul>
</div>
and css
.row {
width: 620px;
clear: both;
overflow: hidden;
}
.rowUl {
width: 645px;
float: left;
}
.rowUl li {
width: 220px;
float: left;
}
but the third list item drop in other row. How can I solve this without extra class?
220 * 3 = 660,
rowUL = 645
thats 15 extra pixels pushing the floated div down.
Solutions:
Make rowUL width 660, make row width 660
OR:
make the rowUL li width 215
Try increasing the width from 645px to a greater value in .rowUl if feasible in your case.
You have 3 floated LI elements, each 220px wide. 3*220 = 660, but the containing element's width is only 645px, so the third one cannot fit in next to the 2nd one and falls to another row below the first one. If you want them all in one row, set .rowUl's width to 660px.
Also, I don't know if you're using some kind of CSS reset - if you don't, be aware of the fact that default margins and paddings of UL and LI elements can also affect this. You need to set them to 0 if you want to make sure that they don't.
You have exceeded width limit of inline elements by 645px within 660px (each 220px for all three elements)
You can do it by increasing width of outer elements more than 660px
Hope this helps
Myra

Resources