Inline-Block vs. Float - Different widths? - css

HTML
<ul>
<li>Item #1</li>
<li>Item #2</li>
<li>Item #3</li>
<li>Item #4</li>
<li>Item #5</li>
</ul>
CSS
ul {
margin: 0;
padding: 0;
list-style: none;
}
li {
display: inline-block;
width: 20%;
}
My Problem
When I use display: inline-block; my <li> elements are acting as if they were wider than if I use float: left;. I have their width set to 20% (100% / 5) but the last <li> is forced to the next line as if the are too wide... When I use float: left; instead of display: inline-block;, the five <li> elements fit as expected (with the same width)...
jsFiddle: Inline-Block vs. Float
I want to use inline-block due to the fact I don't need to use a clearfix to make the parent <ul> expand to the height of the <li> elements... I may decide to use float if I could find the proper way to use a clearfix in this circumstance... Regardless, I would still like to know why inline-block widths are too wide... These <li> elements should fit five-wide on one line as long as the width is 20% and the content inside is not too wide...
The only question I could find that is similar to mine is this one (which didn't help me): css inline-block vs float

It's simple. If you add a background: red to your li rules you will see that there is a small gap between each li. The gap is not a margin or padding but a whitespace character (a space) which is created when the browser 'collapses' your newlines and tabs. The issue here is your inline elements respect whitespace but floated elements do not.
There are several solutions based on your requirements and how 'hacky' you want to get. You can see them here: Ignore whitespace in HTML
Personally I'd use display:table-cell for my li as it enjoys the best browser support and is the least hacky approach
ul.table {display:table; width:100%}
ul.table > li {display: table-cell; padding: 0; margin:0;}
An equally valid (but less readable) solution would be the remove the whitespace from the source like so:
<ul><li>Item #1</li><li>Item #2</li></ul>
This will work in any browser, even IE4. Some people do this with comments to hide the whitespace but I think that's an abuse of comment semantics and still looks ugly in the source anyway.

Related

Using Haml with the inline-block spacing gaps

So I read the solutions regarding making the spacing go away when using inline-block as opposed to floats: display: inline-block extra margin and http://css-tricks.com/fighting-the-space-between-inline-block-elements/.
So if you're using haml and want to put the closing tag on the same line as the next opening tag, is there is a solution besides switching to ERB?
(and no, I don't want to mess with a css property of the parent container and have to override that in all the child elements).
This breaks (has spacing between the anchors).
So is it true that in spite of the recommendations to do such layouts using inline-block as opposed to floats, it seems that floats are still the way to go, especially when using haml?
CSS
nav a {
display: inline-block;
padding: 5px;
background: red;
}
HTML
<nav>
One
Two
Three
</nav>
Workaround (css-tricks one):
<ul>
<li>
one</li><li>
two</li><li>
three</li>
</ul>
or
<ul>
<li>one</li
><li>two</li
><li>three</li>
</ul>
another one:
<ul>
<li>one</li><!--
--><li>two</li><!--
--><li>three</li>
</ul>
I found the answer: http://haml.info/docs/yardoc/file.REFERENCE.html#whitespace_removal__and_
(this is a super useful article on the topic: http://designshack.net/articles/css/whats-the-deal-with-display-inline-block/)
Here's a codepen to experiment: http://cdpn.io/Bjblr
And this worked:
Here's the html if the anchor text is on the same line (same result, but harder to read source html:

CSS - floating LIs - bigger content messes up the next row

<style>
ul{margin:0px;padding:0px;}
ul li{margin:0px 5px 5px 0px;padding:0px;list-style-type:none;float:left;}
</style>
<ul class="clearfix">
<li> </li>
<li> </li>
<li> </li>
<li> </li>
<li> </li>
<li> </li>
</ul>
The first li contains more content than the rest.
So, I have the following problem:
problem http://img830.imageshack.us/img830/240/problemc.png
But how do I move the next row down, so it looks like that:
want this http://img440.imageshack.us/img440/9750/solutionm.png
I tried using display:inline-block; instead of float:left; for the lis, which works, but I'd still rather use float:left; over inline-block.
Any ideas on how to do this?
Solution for IE:
http://blog.mozilla.com/webdev/2009/02/20/cross-browser-inline-block/
The best solution is to use a little-known display style called table-cell.
I've had to do this a few times. Here's how you do it:
/* -*- CSS -*- */
ul li .wrapper
{
display:table-cell;
width:100px; /*replace here*/
min-height:100px;/* " " */
}
ul li
{
float:left;
display:inline-block;
}
ul
{
display:table;
}
...
<!-- HTML -->
<ul>
<li><div class="wrapper">my-content</div></li>
<li><div class="wrapper">my-content</div></li>
<li><div class="wrapper">my-content</div></li>
<li><div class="wrapper">my-content</div></li>
</ul>
How this works:
When the parser sees that there's a UL object, it treats it like a table instead of a list. This gives you the distinct advantage that you're beginning to /act/ like you're working with tables (but you're not!)
The rule then runs against the wrapper class -- this creates a "Table cell". We don't want to put it in the li because OTHERWISE the li will act as the table cell. This is kinda bad. the work around is that your li is actually aligned left. There's some argument whether or not is a good idea to do it this way -- this is the "Most Effective" because it forces the box model to comply. Its fugly, I know.
the REASON its bad for the li to be treated like a table-cell is that it won't wrap. The reason it wont wrap is that table-cells aren't supposed to wrap.
There is ONE other solution that might work, however I haven't tested it.
/* -*- CSS -*- */
ul li { display: inline-block; float:left; min-height:200px;width:200px; }
Its not as ugly, but it should work by making the box model force the alignment as well.
First of all: Are you sure you're using the right markup? A list generally doesn't end up to look like that.
Second. Do you know how many items you will have on a row? In your image they seem to have the same width. If you know that you can add clear:both; to the forth li (and other you may need) and force it down. This would be the only way to do it with left floating lis.
You can't do this using only float:left; the blocks just fall into place where they fit as your first example shows. If you intend for your content to always display in three columns, you could programmatically clear the float on the first item in each row.

CSS3 selectors - select very first item or item after

Let's say a have the following code:
<nav id="main-navigation">
<ul>
<li>Link 1 Level 1</li>
<li>Link 1 Level 1</li>
<ul>
<li>Link 1 Level 2
</ul>
</ul>
</nav>
And now I want to to set first ul's height to 100px and second ul should be 300px.
When I try
nav ul {
height: 100px
}
Second ul also inherits this value.
I was trying "~", "+", ">", first-childs etc. but don't know how to do that, even with documentation.
Is there a good explained (preferably with demos/screens) guide to new css3 selectors? W3 Table is too nerdy for me.
Thanks!!!
Just select any ul that is a descendant of ul and give it that style, if you will only have 2 layers of <ul>s. No need for any special CSS2/CSS3 combinators since <ul> cannot directly contain <ul>, plus you don't have to worry about IE either.
nav ul {
height: 100px;
}
nav ul ul {
height: 300px;
}
To select direct children of an element, and not any descendant, you should use the > syntax. In your case (after you put the second ul inside a li) you need:
nav > ul {
height: 100px;
}
nav > ul > li > ul {
height: 300px;
}
Extra: It doesn't really make sense to have a 300px item inside a 100px item. Why do you want that?
Another extra: Try to read the w3c docs, it will save you some time in the long run. What you don't understand you can always ask on SO.
Firstly, how imporant is browser compatibility to you? All of those selectors you mentioned have issues in various versions of IE (IE8 is obviously better than IE7, but even IE8 is missing a lot of CSS selectors)
Simple nested selectors (ie just a space between the CSS names) will work for you - although as you say, setting nav li {height:100px;} sets it for all the LIs, you can override that with nav li li {height:300px;} to set the inner one back the way you want it.
If you want to use the 'correct' selectors, the one you want is >.
nav>ul>li {
height:100px;
}
This will only affect the outer LI elements, not the inner one. However as I say, it won't work in older versions of IE (fortunately it does work in IE7 and up, so it's only an issue if you want to support IE6).
You say that you've found the various selectors quite hard to grasp. I recommend you visit Quirksmode. For a start, it's got a very handy compatibility chart showing which browsers support which selectors, but it's also got excellent examples of how each selector works, which should help you understand them a bit better.

How to make resizable li elements with CSS only

Scenario: I have an unordered list < ul > of width (lets say 200px) with four < li > elements that are sized equally. Therefore each should be 50px. When I add a 5th < li > element each width should re-size to 40px. If I change the width of the < ul > to 500px with 5 < li > elements, each < li > element should be 100px.
Is this possible with only CSS? If yes, how is it implemented?
Currently, I have a solution that meets the above requirements but it includes jQuery to re-size the < li > elements based on mathematical calculations.
Thanks for the attention.
Aparently you can fake tables like here, but I am not sure if this works in all browsers(edit: it works on winxp ie8, chrome 7, firefox).
<div id="menu">
<ul>
<li>
...
</li>
<!-- other list items -->
</ul>
</div>
#menu {
display: table;
}
ul {
display: table-row;
}
li {
display: table-cell;
}
Also example on fiddle.net here
Your question doesn't completely make sense to me. If you leave the widths off, the list will be as wide as it needs to be. But here's a crack at your question:
<style type="text/css">
ul
{
width:500px;
}
li
{
width:100px;
}
</style>
<ul>
<li>1. one</li>
<li>2. two</li>
<li>3. three</li>
<li>4. four</li>
<li>5. five</li>
</ul>
Using CSS expressions it is possible, but CSS Expressions come with a very heavy performance penalty. JavaScript (and jQuery for that matter) is the appropriate tool to use to create the effect you want.
CSS should only be used for styling, HTML should only be used for structure, and JavaScript should be used whenever you want to create dynamic content.
Until such a time as browsers implement the calc(), min() and max() functions this isn't possible outside of scripting (either server-, or client-, side) or using a table.
Currently, and surprisingly (perhaps only to me), neither Firefox, Webkit or Opera support calc() function, not even with the various flavours of vendor prefix.
That said, one day something like the following might work (but not today, sadly):
ul {
counter-reset: numListItems;
width: 60%;
}
ul li {
counter-increment: numListItems;
width: calc(100%/numListItems);
}
But, obviously, for that to work browsers would need to implement some form, and understanding, of variables within the scope of calc(), which doesn't appear to be necessarily on the road-map (I'm not sure that the counter() is, or is intended to be, interoperable with the calc()).

How to bring the parent element with floated child elements to the center of the document?

I have organized a menu. Its HTML is as follows:
<ul class="topmenu">
<li>Text 1</li>
<li>Text 2</li>
<li>Text 3</li>
<li>Text 4</li>
<ul>
This is a horizontal menu, so I have floated the list items to left to appear them in a horizontal line. I could have used display:inline to appear them in a single line, but since IE does not support it and I don't know any other way to do so, I used float:left;.
It's css is:
.topmenu {
list-style:none;
margin:0;
padding:0;
}
.topmenu li {
float:left;
}
This brings the menu in a perfect horizontal line, but the entire list is floated to the left. I want to bring the .topmenu to appear in the center of the document and keep the listitem inside it floated towards the left.
I found that this is achievable by defining width property of the .topmenu, but I dont want to fix its width as the list-items are dynamically generated and thus could increase and decrease.
Any one know of any solution?
Here is the solution without using width:)
display: inline is supported fine by all versions of IE. It's inline-block that isn't supported completely in IE 6 and 7 (source).
This should be solvable by simply switching to display: inline.

Resources