Using the following markup
<ul>
<li>
<label class="field">
Some Stuff 1
</label>
<input class="value" type="text" />
</li>
<li>
<label class="field">Some Stuff 2</label>
<input class="value" type="text" />
</li>
<li>
<label class="field">Some Stuff 3</label>
<input class="value" type="text" />
</li>
<li>
<label class="field">Some Stuff 4</label>
<input class="value" type="text" />
</li>
<li>
<label class="field">Some Stuff 5</label>
<input class="value" type="text" />
</li>
<li>
<label class="field">Some Stuff 6</label>
<input class="value" type="text" />
</li>
<li>
<label class="field">Some Stuff 7</label>
<input class="value" type="text" />
</li>
<li>
<label class="field">Some Stuff 8</label>
<input class="value" type="text" />
</li>
</ul>
With the following CSS
html, body {
width: 100%;
}
* {
margin: 0;
padding: 0;
border: 0;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
}
input {
border: 1px solid;
}
ul {
list-style: none;
width: 100%;
}
ul > li {
display: inline-block;
width: 25%;
padding: 3px 8px;
}
.field,
.value {
display: block;
width: 100%;
}
Please don't mind how terrible this is its only to demonstrate the problem.
You would expect that there would be 4 li
in a row as there is no margin padding or border to take up any of the space available to them and each is sized to 25% of the parent ul
.
But because we all like to make our markup readable and not just have it all in one line we add extra breaks and tabs/spaces for indenting ect... but this ends up in the DOM as empty text nodes these are of course completely natural and should be there, but since they take up space 4px to be exact they ruin a good fluid layout making use of inline-block.
I don't like to float elements when doing a fluid layout I like to use the display: inline-block
instead there's just this nagging problem with the empty text nodes.
Now I have a fiddle with the solution I use witch is to remove them with javascript you can check it out here or at http://jsfiddle.net/Tt9zn/5/
$(function() {
function tirmSpecial(str) {
// Trim \r Carriage Return, \n Linefeed, \t Tab, \v Vertical Tab, \f Form-Feed, \u0020 Space
// Do Not Trim (u00A0 =  )
return str.replace(/^[\r\n\t\v\f\u0020]+|[\r\n\t\v\f\u0020]+$/g, '');
}
function getTextNodesIn(node, includeWhitespaceNodes) {
var textNodes = [], whitespace = /^\s*$/;
function getTextNodes(node) {
if (node.nodeType == 3) {
if (includeWhitespaceNodes || !whitespace.test(node.nodeValue)) {
textNodes.push(node);
}
} else {
for (var i = 0, len = node.childNodes.length; i < len; ++i) {
getTextNodes(node.childNodes[i]);
}
}
}
getTextNodes(node);
return textNodes;
}
function removeEmptyTextNodes() {
var el, trimVal, nodeList = getTextNodesIn(document, true);
if(Object.prototype.toString.call(nodeList) !== '[object Array]') { return; }
while (el = nodeList.pop()) {
trimVal = tirmSpecial(el.nodeValue);
if (trimVal.length > 0) {
el.nodeValue = trimVal;
continue;
}
el.parentNode.removeChild(el);
}
}
$("#remEmpty").click(removeEmptyTextNodes);
});
To demonstrate what I mean by empty text nodes use IE's developer window and look at the code in my Fiddle before I remove them with javascript.
Now my solution works so far I tested it but I hate how I need to edit the entire DOM just to do this I also found some other solutions on the web some might even be from stackoverflow I just can't remember where but these are all ugly hacks just like mine I will post them below.
Please guys help me out there just has to be a better solution out there.
Someone suggested changing your markup to this
<ul
><li
><label class="field">Some Stuff 1</label
><input class="value" type="text"
/></li
><li
><label class="field">Some Stuff 2</label
><input class="value" type="text"
/></li
><li
><label class="field">Some Stuff 3</label
><input class="value" type="text"
/></li
><li
><label class="field">Some Stuff 4</label
><input class="value" type="text"
/></li
><li
><label class="field">Some Stuff 5</label
><input class="value" type="text"
/></li
><li
><label class="field">Some Stuff 6</label
><input class="value" type="text"
/></li
><li
><label class="field">Some Stuff 7</label
><input class="value" type="text"
/></li
><li
><label class="field">Some Stuff 8</label
><input class="value" type="text"
/></li
></ul>
This works and it gets readable after a while but this has the drawback of everyone in the team remembering to do this awful hack not to mention that auto code indentation is completely broken meaning less productivity for everyone.
Another CSS Hack is to do the following
ul {
list-style: none;
width: 100%;
/* Hack to keep "Text - Empty Text Node" elements from taking up space. */
letter-spacing: -4px;
word-spacing: -4px;
}
ul > li {
display: inline-block;
width: 25%;
padding: 3px 8px;
/* Reverse the Needed Hack to keep "Text - Empty Text Node" elements from taking up space. */
letter-spacing: normal;
word-spacing: normal;
}
This also works but you have to remember to apply and undo the word-spacing hack everywhere you use it also it makes some problems if you actually have text in a section with other inline-block elements that need this hack you will then have to add a <span></span>
or other wrapping element just so you can reverse the hack.