空文本节点&内联块布局

时间:2013-05-29 12:47:13

标签: javascript html css

使用以下标记

<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>

使用以下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%;
}

请不要介意这只是为了证明这个问题有多糟糕。

你会期望连续4个li,因为没有边距填充或边框占用任何可用的空间,每个空间大小为父{{1}的25% }}

但是因为我们都喜欢让我们的标记可读,而不是只将它们全部放在一行中,我们为缩进等添加额外的中断和制表符/空格......但这最终在DOM中作为空文本节点当然完全自然,应该在那里,但是因为它们占据空间4px确切地说它们破坏了使用内联块的良好流体布局。

我不喜欢在进行流畅布局时浮动元素我喜欢使用ul而不是空文本节点的这个唠叨问题。

现在我有一个小提琴,我使用的解决方案是用javascript删除它们你可以在这里或http://jsfiddle.net/Tt9zn/5/

查看它
display: inline-block

为了演示空文本节点的含义,请使用IE的开发人员窗口,然后在使用javascript删除它之前查看我的小提琴中的代码。

现在我的解决方案工作到目前为止我测试了它但是我讨厌我需要编辑整个DOM只是为了做到这一点我也发现了一些其他解决方案在网上有些甚至可能来自stackoverflow我只是不记得在哪里但是这些都是丑陋的黑客,就像我一样,我会将它们发布在下面。

请大家帮助我,那里必须有更好的解决方案。

有人建议将您的标记更改为

$(function() {
    function tirmSpecial(str) {
        // Trim \r Carriage Return, \n Linefeed, \t Tab, \v Vertical Tab, \f Form-Feed, \u0020 Space
        // Do Not Trim (u00A0 = &nbsp)
        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);
});

这有效并且在一段时间后可以读取,但这有一个缺点,即团队中的每个人都记得要做这个糟糕的黑客,更不用说自动代码缩进完全被破坏意味着每个人的生产力降低。

另一个CSS Hack将执行以下操作

<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>

这也有效,但你必须记住在你使用它的任何地方应用和撤消字间距黑客它也会产生一些问题,如果你真的有一个部分中的文本与其他需要这个hack的内联块元素你将会必须添加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; } 或其他包装元素,以便您可以撤消黑客攻击。

2 个答案:

答案 0 :(得分:2)

这是一个相当简单的修复:

ul {
    list-style: none;
    margin-left: 4px;
    width: 100%;
}

ul > li {
    display: inline-block;
    margin-left: -4px;
    padding: 3px 8px;
    width: 25%;
}

无需JavaScript!

编辑:

FWIW,我认为只要接受浮动li元素是实现您想要的最简单方法的事实,您会好得多:

ul {
    clear: both;
    list-style: none;
    width: 100%;
}

ul > li {
    float: left;
    padding: 3px 8px;
    width: 25%;
}

适用于Chrome,FF,Safari,Opera和IE 8+。它在IE 7中失败了,但我相信这是因为IE 7不支持大小调整。

答案 1 :(得分:1)

这个here有一个非常好的跨浏览器解决方案,我在下面的代码中进行了改编: http://codepen.io/pageaffairs/pen/LkaIt

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">

<style media="all">

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%;
}

ul {
    display:table;/* Webkit Fix */
    width:100%;/* set width to stop FF from wrapping li's*/
    text-align:center; /* center list items*/   
    word-spacing:-.25em; /* hide whitespace nodes in all modern browsers (not for webkit)*/
    margin:0;
    padding:.25em 0;
    list-style:none;
}

ul li {
    display:-moz-inline-box; /* FF2 and K-Meleon */
    display:inline-block;
    vertical-align:bottom; 
    word-spacing:0; /* reset from parent ul*/
    /*margin:0 .25em; /*now you can set side margins without node conflict */
    padding:0 .5em;
}

* html ul li { display:inline;} /*IE6*/
*+html ul li { display:inline;} /*IE7*/

</style>

</head>
<body>

<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>

</body>
</html>