【问题标题】:How to position a row of text based on a particular letter?如何根据特定字母定位一行文本?
【发布时间】:2012-03-28 02:09:33
【问题描述】:

我有一行文字如下:

->A B C D E F G H I J                   <-

我想使用 CSS 定位文本行,使 字母 D 位于页面中心,如下所示:

->             A B C D E F G H I J      <-

有什么想法吗?

【问题讨论】:

  • Javascript,即使那样你也需要将每个字母包装在一个元素中。
  • @DavidThomas:那会很复杂,不是吗?
  • @BenHuh 是的,但它不能用简单的 CSS 来完成。曾几何时,有charcharoffs 属性,但大多数浏览器几乎不支持它们。无论如何,如果你告诉我们更多关于这里的上下文,也许我们可以想出一些优雅的东西。
  • @MrLister:感谢您对此感兴趣。其实它是我要创建的一个页面导航栏,当前页码位于中心,相邻页面的链接动态生成在当前页面的左侧或右侧。

标签: html css positioning


【解决方案1】:

发布此内容有两个简单的原因:

  1. 我评论说你需要使用 JavaScript,并且
  2. 有时候,我就是忍不住...

也就是说,这是一个不需要任何库的纯 JavaScript 解决方案。有点繁琐,感觉一定有办法可以简化,不过:

// helper function, to save typing later on.
function gEBTN(tag, parent, index) {
    if (!parent && !index) {
        return document.getElementsByTagName(tag);
    }
    else if (parent && !index) {
        return parent.getElementsByTagName(tag);
    }
    else if (index) {
        return parent.getElementsByTagName(tag)[index];
    }
}

// helper function, to save typing later on.
function gCS(elem, parent, prop) {
    if (!prop && parent) {
        return window.getComputedStyle(elem.parentNode, null).getPropertyValue('width');
    }
    else if (prop && parent == true) {
        return window.getComputedStyle(elem.parentNode, null).getPropertyValue(prop);
    }
    else if (!parent && !prop) {
        return window.getComputedStyle(elem, null).getPropertyValue('width');
    }
    else {
        return window.getComputedStyle(elem, null).getPropertyValue(prop);
    }
}

// page: number.
// navElemId: a quoted string, the Id of the element containing
//            the navigation elements, defaults to 'navigation'
// container: a quoted string, the type of element ('div','span','li'...)
//            that forms the navigation 'buttons.' Defaults to 'li.'
function centreNavigationOn(page, navElemId, container) {
    if (!page) { // at minimum you have to supply the page you want to centre on
        return false;
    }
    else {
        var navElemId = navElemId || 'navigation';
        var navElem = document.getElementById(navElemId);
        var containers = gEBTN(container) || gEBTN('li', navElem);
        for (var i = 0, len = containers.length; i < len; i++) {
            if (containers[i].innerHTML == page) {
                var centreOn = containers[i];
            }
            else {
                // just for an easy visual difference between the centred/current
                // page and the others. Adjust/remove according to taste
                containers[i].style.opacity = '0.3';
            }
        }
        if (!centreOn){
            // if no page is found to be centred on, quits
            console.log('No element found to centre on. Quitting now.');
            return false;
        }

        // again, just for simple visual difference between current and others...
        centreOn.style.backgroundColor = '#f90';
        centreOn.style.opacity = '1';

        // finds the width of the centreOn element
        var cOnWidth = parseInt(gCS(centreOn),10);
        var cOnLeftOffset = centreOn.offsetLeft;

        // the centreOn element's parent's parent's width
        // this made sense when I wrote it, now...I'm not so sure... =/
        cPPWidth = parseInt(gCS(centreOn.parentNode.parentNode),10);

        // works out by what distance the centreOn element's parent
        // must be moved in order to centre the centreOn element within the page.
        var moveBy = Math.round((cPPWidth/2) - (cOnLeftOffset + (cOnWidth/2)));
        centreOn.parentNode.style.marginLeft = moveBy + 'px';
    }
};

centreNavigationOn(4, 'navigation', 'li');​

JS Fiddle demo.

注意事项:在没有window.getComputedStyle() 实现的浏览器(如IE)中,此功能会失效。这可能保证了,尽管组合起来很有趣,但这个脚本不太可能被使用。除了,也许,以修改后的形式(当然,我愿意将此脚本免费提供给任何想要使用它的人,甚至在 Stack Overflow 的 CC-By-SA license 之外发布它,正如我认为 '能够...)。虽然如果有人修改它,我真的很感激他们链接到修改后的版本,无论是在 cmets 中还是通过编辑这个答案来添加链接......

参考资料:

【讨论】:

    【解决方案2】:

    如果您使用monospaced font,那么您可以使用position:relative; 并移动您的文本行,因为每个字母和空格 具有相同的大小(<a href="/default/index/tourl?u=aHR0cDovL2pzZmlkZGxlLm5ldC9TQTdUNC8xLw%3D%3D" rel="nofollow" target="_blank">demo</a>)。您可以在没有固定宽度的字体上获得类似的结果,但是偏移量 (left:;) 有点难以计算,因为几乎每个字母都占用了另一量的水平空间。

    <nav class="letter monospace">
        <div>A B C D E F G H I J</div> <!-- monospaced font demo -->
    </nav>
    <nav class="letter">
        <div>A B C D E F G H I J</div> <!-- standard browser font demo -->
    </nav>
    <div id="leftmiddle"> </div>
    <div id="rightmiddle"> </div>
    
    nav.letter{
        font-size:2em;
        text-align:center;
    }
    nav.letter > div{ /* standard browser font */
        position:relative;
        left:1.05em; /* you have to calculate the horizontal shift yourself based on the font you're using */
    }
    nav.letter.monospace{
        font-family:monospace;
    }
    nav.letter.monospace > div{ /* monospaced font */
        position:relative;
        left:1.75em; /* to center the row around 'E' change to 0.75em, for C to 2.75em... */
    }
    
    nav ~ div{
        width:49%;
        min-height:200px;
        height: 80%;    
    }
    #leftmiddle{ float:left;    border-right:1px solid;}
    #rightmiddle{    float:right;    border-left:1px solid;}
    

    HTML4 demo, working in IE7-9, FF10, Opera, Chrome.

    更新:查看这个替代方案demo(在 IE7-9、FF10、Opera、Chrome 中工作):

    <div class="letter">
        <div class="wrapper">
            <div class="before">
                A B C
            </div>
            D       
            <div class="after">
                E F G H I J
            </div>
        </div>
    </div>
    
    .letter{
        text-align:center;
        overflow:hidden;
    }
    .letter > .wrapper{
        width:1em;
        margin:auto;
        position:relative;
    }
    .letter > .wrapper > .before{
        position:absolute;
        right:125%;
        text-align:right;
        width:10em;
    }
    .letter > .wrapper > .after{
        position:absolute;
        text-align:left;
        top:0;
        left:125%;
        width:20em;
    }
    

    【讨论】:

    • 对不起,我没有说清楚该行文本是动态生成的,这样我可以在字母 D 的左侧或右侧有更多的文本。
    • 哇,你对 CSS 定位有非常好的了解。我希望我能给你+5。真令人印象深刻!
    • 你介意帮我处理this bounty question吗?
    【解决方案3】:

    正如@DavidThomas 所指出的,JavaScript 是必需的。我只是想稍微扩展一下。

    CSS 无法实现这一点有几个主要原因:

    1. 文档流建立之前,无法知道如何更改相关文本行以使D 居中。但是 CSS 的应用是文档流的核心,所以在应用 CSS 的时候,它不可能知道最终生成的文档会是什么。换句话说,如果 CSS 可以用于此,我们手头上就有了第 22 个问题。为了“知道”如何定位该行文本,页面的 CSS 已经需要知道最终文档的外观。但为了得到最终的文档,首先需要应用 CSS。
    2. 即使没有 1 和 2,CSS 仍然无法分析页面、抓取元素的位置等。这根本不是它的目的。

    相比之下,JavaScript可以用来解决这个问题,因为:

    1. 与 CSS 不同,JavaScript 可以在文档流建立后执行其工作。
    2. JavaScript 具有分析页面所需的工具,以便进行必要的更改。

    如果不了解您的具体情况,很难说使用 JavaScript 实现有多复杂。但是,如果您了解 JavaScript,我认为它会相当简单。

    【讨论】:

    • 请查看问题中的第 4 条评论以了解我的应用程序的上下文,谢谢。
    【解决方案4】:

    也许使用类似的东西

    <div id="container" style="position: absolute; width:1000px; height:10px">
        <div id="innerContainer" style="position: absolute">
            <span>A</span><span>B</span><span>C</span><span>D</span><span>E</span><span>F</span>
        </div>
    </div>
    

    然后在 $(document).ready() {}

    中的 JQuery 中类似以下内容
    var left_pad = 20; // set this to container width / 2
                       // calculate it or hard code it
    $("#innerContainer").css("left"),$((left_pad - span:contains('D').position().left) + 'px')
    

    只是在我的脑海中,没有时间测试,但希望它为您指明正确的方向。稍有耐心,这应该可以开始工作了。

    【讨论】:

    • 是的,可能是一个解决方案,但仍然需要 jquery。我正在考虑使用边距和负边距。让我先试一试。谢谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-29
    • 1970-01-01
    • 1970-01-01
    • 2015-06-25
    • 1970-01-01
    相关资源
    最近更新 更多