Padding with and without child - css

I am styling a simple menu and I'm having an unbelievably hard time figuring out how to put padding in list items so that they look the same.
I have an unordered list, where list items may contain an anchor, if that is the case I want the whole body of the visible element to be clickable ( in other words the anchor should occupy 100% width and height of the list item ), however if there is no anchor the list item should still be the same height/width as the other list items.
HTML
<ul>
<li>Index</li>
<li><a href=''>Home</a></li>
<li>FAQ</li>
</ul>
CSS
ul { padding:0; margin:0; width: 200px; background: lightgray; }
li { padding: 20px; border: solid black; }
li a { display: block; }
DEMO
If I put the padding on a then items without a child dont have padding, if I put it on both then items with a child become fatter, and in the case I show in the fiddle there is an area of the list item that is not clickable. How can I fix this?

If I put the padding on a then items without a child dont have padding, if I put it on both then items with a child become fatter
Well, then send them on a diet – by reversing the “fattening” effect of the padding on the links by a negative margin of the same amount:
li a { display:block; margin:-20px; padding:20px; background:red; }
http://jsfiddle.net/rph4bg0j/11/
(Red background only added so the effect shows up directly.)

Related

Get children to line up centred or middle

JS Fiddle here
I am attempting to align child elements evenly between left and right. I tried using margin-left and right: auto but nothing happened.
Here is a screen shot of the navigation in question. I have added a border of 1 px around each element so you can see:
I'd like the nav line items to be centred in comparisson to their parent. So in the image the line items would move to the right a bit to be centred between the parent rectangle, which is an unordered list.
Here is my approximation of the relevant html:
<nav>
<div id="main-nav">
<ul id="menu-main">
<li>cats</li>
<li>dogs</li>
<li>sheep</li>
</ul>
</div>
</nav>
Currently relevant (I think) CSS is:
#main-navigation {
display: inline;
float: left;}
#main-navigation div {
display: block;}
#menu-main {
position: relative;
float: left;}
#menu-main li {
float: left;
}
Put another way, I'd like to centre floated child elements against the parent. If I zoom in and out with my browser I can see that the nav adjusts and change size with some line items moving between top and bottom row in order to fit.
But is there a way to ensure that, whatever the current size of the nav, the child line items will be centred?
Here's another picture, where I have manually added a margin left to #menu-main.
Now it looks more centred on my screen right now. But is there a way to auto centre it?
See this : http://jsfiddle.net/rahjrLny/1/
You don't need to float your li elements, simply set them to display:inline . Then you can add text-align: centre to your ul element, and all should be good.
(You'll need to remove some margins that have appeared in the fiddle due to the changes)
This would be my solution: JSFiddle
There's some redundant CSS (for example, no need to specify #main-navigation div {display: block;} if you don't have any div elements inside the #main-navigation).
I've gone with display:inline-block as opposed to display:inline (plus added some colour borders for visual clarity). Please bear in mind I'm working with the code you supplied in the question rather than building the code from the screenshots.
nav {display:inline-block; width:100%;}
#main-nav {
float:left;
width:100%;
}
ul#menu-main {
margin:0;
padding:0;
text-align:center;
width:100%;
float:left;
}
#menu-main li {
list-style: none;
padding: 0.5em;
display:inline-block;
}
EDIT: I answered this question before I observed there was a fiddle supplied, and worked instead from the code supplied in the question. This may not be the right answer for OP but I'm going to leave it alone for now as I believe it gives a valid example of how one could approach the task of centering a nav list.

css make inline-block elements span the whole width of container

OK so this is actually a little complicated.
I have a navigation list where the list items are set to inline-block. The number of items is the list is dynamic so may vary.
My aim is to have the list items span the whole width of the container. (e.g. if there were 4 list items each one would take up 25% of the container width [ignoring margin/padding etc])
There is the added complication that browsers seem to add a 4px margin to inline-block elements where there is whitespace between them (linebreak/space etc).
I have made a fiddle as a starting point which has 2 examples: the first is just the list items in inline-block mode which the 2nd justifies them accross the width.
Neither achieves what I want which is for the whole width to be taken up by the elements without them breaking onto another line.
http://jsfiddle.net/4K4cU/2/
edit: slightly separate but why in my 2nd example is there a space beneath the lis, dispite the fact I have set line-height and font-size to 0?
OK, despite many decent answers and my inital thinking that js/jquery was the only way to go there is in fact a good css-only solution: using table cells. Original suggestion by #Pumbaa80
.list {
margin:0;
padding: 0;
list-style-type: none;
display: table;
table-layout: fixed;
width:100%;
}
.list>li {
display: table-cell;
border:1px green solid;
padding:5px;
text-align: center;
}
.container {
border: 1px #777 solid;
}
<div class="container">
<ul class="list">
<li>text</li>
<li>text</li>
<li>some longer text</li>
<li>text</li>
</ul>
</div>
This is superior to other solutions as:
css-only
no 4px margin problem as with inline-block
no clearfix need for floated elements
maintains equally distributed width independent of li content
concise css
Fiddle here: http://jsfiddle.net/rQhfC/
It's now 2016 and I wanted to update this question with an answer using flexbox. Consult with CanIUse for browser-compatiblity.
/* Important styles */
ul {
display: flex;
}
li {
flex: 1 1 100%;
text-align: center;
}
/* Optional demo styles */
* {
margin: 0;
padding: 0;
}
ul {
margin-top: 2em;
justify-content: space-around;
list-style: none;
font-family: Verdana, sans-serif;
}
li {
padding: 1em 0;
align-items: center;
background-color: cornflowerblue;
color: #fff;
}
li:nth-child(even) {
background-color: #9980FA;
}
<ul>
<li>text</li>
<li>text</li>
<li>text</li>
<li>text</li>
</ul>
Pre-edit fiddle (now inlined in above snippet)
Here is one way of modifying your original concept.
The CSS is:
.list {
padding:0;
margin:0;
list-style-type:0;
overflow: hidden;
height: 42px;
}
.list li {
display: inline-block;
line-height: 40px;
padding: 0 5px;
border:1px green solid;
margin:0;
text-align:center;
}
On your parent container, .list, set a height to enclose the child elements.
In this case, I chose 40px and added 2px to account for the border.
Also, set overflow: hidden on .list to hide the 2nd line generated by the pseudo-element.
On the li elements, set line-height: 40px which will center the text vertically.
Since the height is fixed, the second line gets hidden and you can style your parent with a border and so on without extra white space breaking the design.
Demo: http://jsfiddle.net/audetwebdesign/WaRZT/
Not Foolproof...
In some cases, you may have more links than can fit on a single line. In that case, the items could force a second row to form and because of overflow hidden, you would not see them.
Evenly Spaced Border Boxes
If you want the border boxes to be evenly distributed, you need to set a width to the li elements.
If the content comes from a CMS, and you have some control over the coding, you can dynamically generate a class name to set the correct width using predefined CSS rules, for example:
.row-of-4 .list li { width: 24%; }
.row-of-5 .list li { width: 19%; }
.row-of-6 .list li { width: 16%; }
See: http://jsfiddle.net/audetwebdesign/WaRZT/3/
There are multiple fixes to this. The one I prefer is simply to remove the whitespace between the elements, simply because the font-size trick involves non-semantic CSS. And its a lot easier haha. Code because answer requires it:
<ul class="list">
<li>
text
</li><li>
text
</li><li>
text
</li><li>
text
</li>
</ul>
Updated jsFiddle, where the first list has items set to width:25%; and fits in the window on one line. If this isn't what you were going for, I must have misunderstood.
EDIT: for unknown number of list items
There is some CSS3 stuff for this, but to be cross-browser compatible back to IE8, you want a JS solution. Something like this should work:
var listItems = document.querySelectorAll('li');
listItems.style.width = listItems.parentNode.style.width / listItems.length;
SECOND EDIT: for jQuery instead of JS
Winging it, but:
var $listitems = $('.list').children();
$listitems.width($listitems.parent().width()/$listitems.length);
you can use the display:inline-block with li element,and use the text-align:justify with ul element. If you are interested ,please click here.

top navigation list item margin bug

I am making a website's top navigation. There is a margin bug with the menu.
I have defined margin / padding : 0 for list items as well as display: inline-block.
See the demo: http://tinkerbin.com/495Qb956
Basically I want to remove that left/right margin from the list items, and know why this margin is there.
By default display:inline-block take margin from left. Write like this:
.top-right ul {
background:black;
height:43px;
font-size:0;
}
.top-right ul li {
display:inline-block;
border:1px solid red;
margin:0;
padding:0;
font-size:13px;
}
Check this http://tinkerbin.com/YWeV7osy
That room you're seeing are spaces between the blocks. If you remove all white-space between the </li> and <li> you'll see the space disappear. Basically an inline-block will behave like a word in a sentence, and any white-space between two of those blocks will be folded into 1 space char.
One solution is to use floats to make the blocks stick together:
li { float: left; }
You might need to clear the elements that come after such floating elements.

CSS: how to properly style horizontal menu bar with background image and centered entries separated by icons

I have come across the following problem. I have a horizontal menu bar I would like
to style towards the top of the page. Here is what its html is like:
<body>
<div id="container">
<div id="left">
</div>
<div id="center">
<!-- stuff above header here ... -->
<div id="header">
<ul>
<li class="first">Products</li>
<li>Customers</li>
<li>Invoices</li>
</ul>
</div>
<!-- stuff below header here ... -->
</div>
</div id="right">
</div>
</div>
</body>
I want it to appear like this:
+--------------------+-----+--------------------+-----+--------------------+
+ + + + + +
+ Products + / + Customers + / + Invoices +
+ + + + + +
+--------------------+-----+--------------------+-----+--------------------+
Basically, I need the following:
the whole page is fixed width (960px) in the center (id="center")
and has expandable variable-size sidebars (id="left" and id="right").
the navigation bar spans the center div and is hence also 960px wide
the navigation bar has a background image which is 960px wide and has
a height which is known (not sure if the fact the height of the navigation
bar is known makes a difference to the CSS styling).
The parts labeled "/" are images which display this "/" character. These
images are the same height as the navigation bar and have a width of 30px.
I want the area containing the each one of the links Products, Customers,
and Invoices, to be the same width, regardless of differences in the width
of the text. The width of each should be 300px.
If one of the links has a name that is very long (e.g. if we had
"Super Long Heading for the List of Products" instead of just "Products"
in one of the headings then the text should not wrap to the line below,
but should instead be cut off (perhaps displaying an ellipsis at the end
of the text). In practice we want the text to fit completely all the time,
given that the width of the center div is fixed, so assigning a smaller
font is imperative.
I want each of the Products, Customers, and Invoices links to be centered
vertically as well as horizontally within its bounding box.
That's all, this is all I have been trying to do.
But I am having problems centering the text, in part because I can never tell
whether I should apply a property to an element (e.g. a, or to its parent div,
or to its grandparent div), and I don't know whether some properties are inherited
all the way down the DOM tree or whether inheritance only depends on which elements
are adjacent in the DOM tree as being involved in a parent-child relationship.
So far I figured out how to take care of 1. as follows:
div#left { float: left; }
div#right { float: right; }
div#center { width: 960px; margin: 0px auto; }
I have also sliced the header background and header divider from the PSD/JPG mockup.
However, I cannot get the rest to work, in particular 5. and 7.
Any suggestions?
OK, here is what I ended up doing:
In this case, since the image is a separator and not an item indicator, you
can not set it with list-style-image inside the ul element because that would
mean also having the image at the right of the first image, which would produce
the wrong effect.
So my solution was to clear: both on the containing div to make sure it appears on
a line by itself. Then set the ul's list style to none. And then if W is the width
of the header div and there are N hyperlinks in the menu, then compute:
floor({W - [(N - 1) * SEPARATOR_IMAGE_WIDTH]} / N) to compute the width of each
link containing block, and set it for each li element. Also set a padding of
SEPATATOR_IMAGE_WIDTH and a background for each li except for the first one.
Then set the height for the ul, li, and a link to the height of the separator image,
to keep it from collapsing. You can use the inherit attribute instead of the line
height if you don't want to write down 40px all the time.
Center the text in the a link with text align and use some top padding to move the text
a little bit down from the top (as I couldn't find a better way to center the text
vertically within those 40px, any ideas here welcome)
div#header_middle { clear: both; }
div#header_middle ul { list-style: none; background: url(images/header_middle_navbar_background.jpg); height: 40px; }
div#header_middle ul li { float: left; padding-left: 14px; background: url(images/header_middle_entryseparator.jpg) no-repeat; height: 40px; }
div#header_middle ul li.first { padding-left: 0px; background: none; }
div#header_middle ul li a { display: block; float: left; text-transform: uppercase; font-size: medium; width: 110px; text-align: center; padding-top: 8px; height: 40px; color: white; }
Here is a start, show us that you can at least check a few more numbers off that list:
div#header {background-color: green; text-align: center;}
#header li { display: inline-block; }
#header li a { width:300px; display: block; text-align: center; background-color: red;}
By the way, why not just Google a horizontal-navigation-bar and copy it?

How to stick the last menu item automatically to the right corner?

I'm trying to create a menu, in which the last menu item (with different class) will stick automatically to the right corner of the menu. I'm attaching a screenshot for this. There are a few menu items on the left and the last item should somehow count the rest of the available space on the right in the menu div, add this space as padding to the right and display a background in whole area ON HOVER (see the screen to understand this please)
Is something like this possible?
Thanks a lot
See if this will work for you: http://jsfiddle.net/neSxe/2
It relies on the fact that non-floated elements get pushed out of the way of floated elements, so by simply not floating it the last element fill up the rest of the space.
HTML
<ul id="menu">
<li>Services</li>
<li>Doctors</li>
<li>Hospitals</li>
<li>Roasted Chicken</li>
<li class="last">Customer Service</li>
</ul>
CSS
#menu {
width: 600px;
}
#menu li {
float: left;
}
#menu li a {
display: block;
padding: 6px 14px 7px;
color: #fefefe;
background-color: #333;
float: left;
}
#menu li a:hover {
background-color: #666;
}
#menu li.last {
float: none;
}
#menu li.last a {
text-align: center;
float: none;
}
Edit
I've made some changes to make it work smoother on IE6, by floating the anchors too.
If anybody else needs this and do not need to support IE6 and below, you can get rid of those two properties.
assuming your html looks like this:
<div id="menu">
<div class="entry">Services</div>
...
<div class="entry last">Support Staff</div>
</div>
I would make the #menu position: relative;, so that you can position the last menu entry absolute inside the #menu div.
Not necessarily putting the menu item last, but if you always wanted that rounded corner at the end then you could apply a background image to the ul itself and position that right top with the curve. The only issue you'd run into with this method is, if you hover over the last menu it will not put a hover right to the right-hand edge.
If you knew how many menu items there were you could achieve this by setting the correct widths for all your menu items?
Have a look at this:
http://jsfiddle.net/ExLdQ/
The trick is to use your lighter green as the background or background-image for the whole list. You can than use the darker green on all li's and add a background-color:transparent to li.last.
Just add float: right; to your css for the last menu item, and use light background for both the list itself and the last menu item.

Resources