I want to position list elements inside a bordered div, so they will go "all the way" from right to left, and to take exactly 960px width, but for some reason I can't space between them to catch all the 960px.
HTML:
<div class="wrapper">
<ul>
<li class="menu red">1</li>
<li class="menu blue">2</li>
<li class="menu yellow">3</li>
<li class="menu yellow">4</li>
</ul>
</div>
JSFiddle: http://jsfiddle.net/yuvalsab/MvaeF/
I'd use the display: table and display: table-cell technique. This way, you don't have to define a width on your items.
div.wrapper {
width:960px;
margin: 0 auto;
}
ul {
border:5px solid black;
display: table;
width: 100%;
margin: 0;
padding: 0;
}
ul li.menu {
display: table-cell;
height: 120px;
text-align: center;
padding: 55px 0 0 0;
border: 8px solid;
font-size: 25px;
}
Demo
You need to remove default paddings on ul and possibly margins on li's.
ul {
border:5px solid black;
margin:0;
}
Check this: http://jsfiddle.net/MvaeF/2/
First of all... you need to check your match.
960 - UL 5px Padding (5 x 2 = 10) = 950 for the LIs.
That leaves you with 950.
Divided by 4, and you have 237.5 each.
Now, you have 8px border... so 4 x 2 = 16.
237 - 16 = 221px wide for the LI.
Note, you have it at 200px not 221... so that is some of the space issue you're seeing.
The other issue, natively, the browser gives UL and LIs Margin, different amounts for different browsers. If you are not normalizing, then you have to manually.
ul, li {margin:0px; padding:0px; }
That will ensure that doesn't interfere with your math.
I think you just edited it.
Regardless... use the 0 padding and 0 margin.
Then make sure your math is solid.
Related
I have a ul element and 5 child <li>.
<ul>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
The <ul> has a display: flex property.
I tried using the calc property on the <li> to evenly size my list items:
calc:(100% / 5);
This gives the desired result and evenly sizes the 5 <li> blocks
Now I added borders to the right side of all, but the last child <li> element. So I reduced the total width of all the borders combined from the total width of the <ul>.
calc:((100% - 8px) / 5);
This also worked properly and evenly sized the <li> blocks with the borders.
ul {
width: 600px;
height: 300px;
margin: 0;
padding: 0;
display: flex;
background: red;
}
li {
list-style: none;
display: block;
width: calc((100% - 0.8px) / 5);
height: 100%;
border-right: 0.2px solid black;
background: blue;
}
li:last-child {
border-right: none;
}
<ul>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
Now I tried to set the border width in viewport unit vw instead of px but it gives a different result.
ul {
width: 600px;
height: 300px;
margin: 0;
padding: 0;
display: flex;
background: red;
}
li {
list-style: none;
display: block;
width: calc((100% - 0.8vw) / 5);
height: 100%;
border-right: 0.2vw solid black;
background: blue;
}
li:last-child {
border-right: none;
}
<ul>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
As you can see from the snippet above, there is a little bit of space to the right. This becomes bigger with a wider viewport (try viewing the snippet full page). So I think the problem lies with the vw units and flexbox here.
So what is the cause of this error?
EDIT:
From the provided answers and comments, I have seen there are other and more proper approches to achieve what I was trying to do. I appreciate those answers but those are not the answers to my question. Since calc is showing an error in this case, most likely it will cause more problems when I try to use calc and viewport units in other cases (not just borders). So I need to know the reason and "calc" fix.
You don't need to do calc to add inner content for your li. If you give the box-sizing: border-box; prop, border and padding will not make the container grows.
ul {
width: 600px;
height: 300px;
margin: 0;
padding: 0;
display: flex;
background: red;
}
li {
list-style: none;
display: block;
width: calc(100% / 5);
height: 100%;
border-right: 2px solid black;
background: blue;
box-sizing: border-box;
}
li:last-child {
border-right: none;
}
<ul>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
It seems you are using flex to distribute your lis inside of your ul. In this case, you do not need to calculate the widths to make those equal. That is what flex is supposed to do.
See this example:
* { box-sizing: border-box; margin: 0; padding: 0; }
ul, li { list-style: none; }
ul { width: 600px; height: 300px; background: red; display: flex; }
li {
flex: 1 0 auto;
border-right: 0.8vw solid black;
background: blue;
}
li:last-child { border-right: none; }
<ul>
<li></li><li></li><li></li><li></li><li></li>
</ul>
When specifying flex dsiplay on containers, you just need to apply the flex property on the children to make them behave as flexible items. In your specific use-case, you need the following:
flex-grow: set to 1. This will allow your li to grow to fill the entire ul width.
flex-shrink: set to 0. You do not want your li to shrink.
flex-basis: set to auto. You want your li to grow to an equalized width automatically.
So, you see, you do not need calc at all.
You also, need not to specifically apply display: block to your lis. As per the specs here: https://www.w3.org/TR/css-flexbox-1/#flex-items
The display value of a flex item is blockified: if the specified
display of an in-flow child of an element generating a flex container
is an inline-level value, it computes to its block-level equivalent
As pointed out by #BoltClock in the comments, the list-item is already blockified.
Borders
Now, coming to borders. In your first example you have specified the width in 0.2px unit. This makes no sense. Although the specs allow fractional pixels, it will round it off to the nearest pixel available on display which is usually 1.
In you second example, you want the borders to scale with the viewport. That's good. No problem with the 0.8vw.
Just see the example I posted, in this fiddle. Resize the result window and you will see the borders changing relative to the viewport size.
Lastly, you may or may not want to set the box-sizing. It depends on your layout. Whatever you use, you use it consistently.
Pixels (px): Absolute pixels. So for example, 20px will be literally 20 pixels on any screen. If a monitor is of 1980x1200, and you set an element's height to 200px, the element will take 200 pixels out of that.
Viewport height/width (vw/vh): Size relative to the viewport (browser windoe, basically).
1px = (100 / document.documentElement.clientWidth)vw
1px = (100 / 500) = 0.2vw
Let's keep this simple and short, I've made 2 dummy examples of my problem.
I have a container section which is 600px wide, this section will container list of products.
each product is a 100x100 block, and there is a margin of 62px between each product.
The ul is set on display: inline-block so it won't go one under each other.
Now in the following pen example: http://codepen.io/anon/pen/yujLf
You can see what I want to do, can you see how the first row of squares, touch the border of the container & then the next element goes under?
(source: gyazo.com)
You can see how it's perfectly aligned for the width, as there's a perfect equal margin between each element.
Now this solution is a problem, because now the second row will have extra margin on the left side:
(source: gyazo.com)
I do have a solution for that, simply by changing margin-left to margin-right and disable margin-right for ul li:last-child.
But if I do that, I will not be able to align the last element with the border, like I did with the first example, take a look: http://codepen.io/anon/pen/wdhrJ
As you see, I had to change the margin to 40px instead of 62px to make it 4 elements per row.
Is it possible to implement what I want with using ul?
If your container is fixed at 600px, then the following solution will work:
ul li {
width: 100px;
height: 100px;
background-color: red;
margin-right: 62px;
display: inline-block;
}
ul li:nth-child(4n+4) {
margin-right: 0;
}
What I've done is change margin-left to margin-right in both of the above selectors. I've also changed your second selector from first-child to nth-child, to select the 4th element and every 4th element after that.
CodePen Example
Have you tried this hack instead? http://codepen.io/anon/pen/IgKtD
* {
padding: 0;
margin: 0;
}
ul {
list-style: none;
padding: 0;
margin: 0;
text-align:justify;
vertical-align:top;
font-size:0.001px;
}
ul::after {
content:'';
display:inline-block;
width:100%;
height:3px;
background:blue;
}
ul li {
width: 100px;
height: 100px;
background-color: red;
display: inline-block;
box-shadow: inset 0 0 0 1px purple;
margin:0 20px;
}
ul li:nth-child(4n), ul li:last-child {
margin-right:0;
}
ul li:nth-child(4n-3) {
margin-left:0;
}
I'm trying to make a banner on my webpage, the part on the top that is 700px wide and 80px high.
Code looks like:
<div class="container-narrow" style="heigth: 80px;">
<img src="#" width="52" height="52" alt="my logo" />
<ul>
<li>About</li>
<li>Projects</li>
<li>Contact</li>
</ul>
</div>
Css:
.container-narrow
{
margin: 0 auto;
max-width: 700px;
background: yellow;
}
ul
{
float: right;
width: 100%;
padding: 0;
margin: 0;
list-style-type: none;
}
a
{
float: right;
width: 6em;
color: black;
text-decoration: none;
padding: 0.2em 0.6em;
}
a:hover {color: #ccc; text-decoration: none;}
li {display: inline;}
What I want is the image and the horizontal menu to be vertically aligned in the center of the 80px. the logo to the left and the menu to the right.
I've tried to set the height and then padd/margin my way to get the job done but it feels rubbish...
Problem:
ul has a width:100%; if you give it a black border you will see that its occupying the width of the page, means it has no space to reside on the left of the logo inside the yellow header.
Removing this width will give the following result: http://jsfiddle.net/YBVe6/
Now since the header has a fixed max width, which is 700px, there's many ways to center the logo and the menu.
Fastest way I can think of is the following:
Give ul a display: inline-block;, (remove float: right;) then give the header a text-align: center;, here's the result : http://jsfiddle.net/YBVe6/1/
And if you want the menu to be displayed in the upper part, just add vertical-align: top;.
To start of, it's a good practice if you have an external CSS, don't put additional CSS in your HTML blocks:
<div class="container-narrow">
and put the height style in your css sheet, as you have a class setup for your div there anyway.
Second, making typo's is a pain if you want your CSS to work properly, so instead of heigth you should use height, will make you div actually 80px high.
Third of all: margins are there the position elements. Use them!
.container-narrow
{
height: 80px;
margin: 0 auto;
max-width: 700px;
background: yellow;
}
img
{
margin-top:14px;
}
ul
{
float: right;
padding: 0;
margin: 0;
list-style-type: none;
margin-top:25px;
}
a
{
width: 6em;
color: black;
text-decoration: none;
padding: 0.2em 0.6em;
}
a:hover {color: #ccc; text-decoration: none;}
li {display: inline;}
Edit
This is mostly applicable for vertical alignment. If you want to auto-center horizontally, you can make use of the margin:auto concept. This is possible because a page can't extend beyond the browser width (browser height can extend as you have scrolling available as default behavior).
I am trying to create a navigation panel for my website. I would like it to consist of:
Four tabs in equal size with text-centered in each tab.
They should fill the whole page width.
I would really like the design to be flexible and browser friendly. I have tried various float techniques, but I can't get it to work. I hope that you can help me out!
Thank you.
HTML
EDIT: it's 2015 and HTML5 has been there for a while; following code should be inside a nav element (html5doctor) with landmark ARIA attribute role="navigation" on it (and 99.9% of the time be unique in any given page).
A navigation panel should use an unordered list of links:
<ul id="nav">
<li>One</li>
<li> Second</li>
<li>Third</li>
<li>Fourth and last, so large that... worst case</li>
</ul>
CSS
EDIT2: It's 2017, just use Flexbox 😲 (with or without flex-wrap: wrap)
inline-block is useful but has one drawback: whitespace between two elements must be carefully managed. Whether removed or no </li> in HTML5 or </li> at the beginning of the following line stuck like </li><li>next item or other tricks, you still have to do something or it'll create a ~4px gap between 2 elements.
25% + 25% + 25% + 25% doesn't equal 100% on all browsers if the total isn't a multiple of 4. Each browser has its own rounding method.
If you want elements to total 100% width and equal width, another method is to use display: table (and table-cell) with table-layout: fixed to force browsers to use the other table algorithm, the one that doesn't try to adapt cells width to content but respect the widths wanted by the designer/developer as far as possible.
ul {
margin: 0;
padding: 0;
}
li {
list-style-type: none;
}
#nav {
display: table;
table-layout: fixed;
text-align: center;
}
#nav li {
display: table-cell;
width: 25%;
padding-right: 1px;
height: auto;
vertical-align: bottom;
}
#nav a {
display: block;
min-height: 100%;
padding: 4px 10px;
background-color: #222;
color: white;
border-radius: 6px 6px 0 0;
}
Fiddle
http://jsfiddle.net/PhilippeVay/aHCy3/1/
edit: http://jsfiddle.net/PhilippeVay/aHCy3/2/ with another method for space between each tab, courtesy of my colleague.
You don't need floats for this. Just set the width to 25%, or a tiny bit less than 25%. If you're using this on a block level element, set display: inline-block. This will work for all browser sizes, as well as respond to window resize.
HTML
<div class="nav">Nav 1</div>
<div class="nav">Nav 2</div>
<div class="nav">Nav 3</div>
<div class="nav">Nav 4</div>​
CSS
body, html {
width: 100%;
padding: 0;
margin: 0;
}
.nav {
width: 24%; /*Slightly less than 1/4th of the width*/
display: inline-block;
padding: 0;
margin: 0;
text-align: center;
}​​
Live demo
css:
.tab {
float: left;
width:25%;
height:25px;
background:black;
border:1px solid #fff;
box-sizing: border-box;
}​
html:
<div class="tab"></div>
<div class="tab"></div>
<div class="tab"></div>
<div class="tab"></div>​
jsfiddle: http://jsfiddle.net/zP7Xh/6/
Although li.textmenu has width: 140px, padding: 5px, and div.textmenu has width: 150px, the one list item i've made so far has a big left margin, and extends beyond the right edge of the div by at least 30px. What could be causing this and how can I restrict it's width?
http://www.briligg.com/frailty.html
CSS
div.textmenu {
background-color: #3b3b3b;
float: left;
width: 150px;
margin: 30px 10px 0 30px;
}
li.textmenu {
background-color: #4a4a4a;
margin: 0;
padding: 5px;
border: none;
width: 140px;
list-style: none;
text-align: right;
}
HTML
<div class="textmenu">
<ul>
<li class="textmenu">
<a class="pink" href="http://www.briligg.com/frailty.html#culture">Stress Causes Addiction</a>
</li>
</ul>
</div>
Did you add a zip/uni reset to the top of your css file?
* { margin:0; padding:0; }
( Put that exactly as is at the very top of CSS to override browser default margins/padding ).
Most likely the ul is being given default padding/margin, so this is to counter-act it.
Make sure the ul does not have padding and margin of its own, by resetting it with padding:0;margin:0;
The ul has a margin and padding set it on by the browser. You'll want to remove this:
div.textmenu ul {margin:0;padding:0;}
Only the padding affects the width, but you'll probably want to take off the margin too.
Its like smeridan said. There are for all html elements preset styling properties.
I recommend you to use the reset css by Eric Meyer: http://meyerweb.com/eric/tools/css/reset/
You can include it at the top of your document. After that you have more control about your desired styling.
Make sure you've calculated the exact width and height of the Li you want to fix inside the Div by making sure the DIV has enough space within it.
div.textmenu {
background-color: #3b3b3b;
float: left;
width: 150px;
margin: 30px 10px 0 30px;
}
li.textmenu {
background-color: #4a4a4a;
margin: 0;
padding: 5px;
border: none;
width: 140px;
list-style: none;
text-align: right;
}
Since you made the padding: 5px, calculated by the 2xwidth + height of the Li, the Li should exceed 150px width of the Div box. you can fix by reducing your padding pixel of the LI.