如何将一段文本居中于HTML,CSS或JavaScript中的特定单词?

Vil*_*age 20 html javascript css centering

我有一个以页面为中心的段落,如下所示:

 _________________________
|                         |
| Once upon a time, there |
|   lived a squirrel who  |
|  lived in the middle of |
|       the forest.       |
|_________________________|
Run Code Online (Sandbox Code Playgroud)

我需要调整居中,使得特定标记的单词在页面上水平居中.在此示例中,单词"who"居中:

 _________________________
|                         |
|        Once upon        |
|  a time, there lived a  |
|  squirrel who lived in  |
|    the middle of the    |
|         forest.         |
|_________________________|
Run Code Online (Sandbox Code Playgroud)
  • 在HTML中用标记标记的单词<div>,即<center>Once upon a time, there lived a squirrel <div style="centered">who</div> lived in the middle of the forest.</center>.
  • HTML出现在一个应用程序中,我几乎无法控制HTML本身的编辑(文本已经标记了CSS样式标记),但可以修改样式表或添加代码(如JavaScript)到标题以修改样式的方式被渲染.

如何在HTML,CSS或JavaScript中以特定单词为中心?

Lev*_*man 13

[编辑]添加小提琴.清理了一些代码.下面更新了代码段.添加了评论.

http://jsfiddle.net/2Hgur/

[ORIGINAL]我不相信这可以用css.但是,我认为使用JavaScript可以实现解决方案.所以,我试过了,它有效!虽然这可能不是最终解决方案,但请考虑以下事项:

<div class="jsCenterOnPhrase">

The quick brown fox jumped over the lazy dog.
The quick brown fox jumped over the <div class="jsCenteredPhrase">lazy dog.</div>
The quick brown fox jumped over the lazy dog.
The quick brown fox jumped over the lazy dog.
The quick brown fox jumped over the lazy dog.

</div>
Run Code Online (Sandbox Code Playgroud)

然后分解并重建它,也许是这样的:

jQuery(function ($) {

var $divParents = $('.jsCenterOnPhrase'); // all instances
var sMarker = '##'; // marker for phrase position

// for each instance
$divParents.each(function () {

    // closures
    var $parent = $(this);
    var $phrase = $parent.find('div.jsCenteredPhrase');

    // if there is only one phrase
    if ($phrase.size() == 1) {

        // more closures
        var iParentWidth = $parent.innerWidth();
        var sPhrase = $phrase.text();
        var iPhraseWidth = $phrase.outerWidth();
        $phrase.replaceWith(sMarker);
        var sFullText = $parent.text().replace(/\s+/g, ' ');
        // add html structure to container
        $parent.html(
            '<span class="jsLeftWrap"></span>' +
            '<span class="jsCenterWrap">' +
            '<span class="jsCenterPrefix"></span>' +
            '<span class="jsCenterPhrase"></span>' +
            '<span class="jsCenterSuffix"></span>' +
            '</span>' +
            '<span class="jsRightWrap"></span>');
        // more closures
        var $LeftWrap = $parent.find('.jsLeftWrap');
        var $CenterWrap = $parent.find('.jsCenterWrap');
        var $CenterPrefix = $parent.find('.jsCenterPrefix');
        var $CenterPhrase = $parent.find('.jsCenterPhrase');
        var $CenterSuffix = $parent.find('.jsCenterSuffix');
        var $RightWrap = $parent.find('.jsRightWrap');

        // get all the words left and right into arrays
        var iLeftStart = 0;
        var iLeftEnd = sFullText.indexOf(sMarker);
        var iRightStart = iLeftEnd + sMarker.length;
        var iRightEnd = sFullText.length - 1;
        var sFullLeft = sFullText.substring(iLeftStart, iLeftEnd);
        var sFullRight = sFullText.substring(iRightStart, iRightEnd);
        var aFullLeft = sFullLeft.split(' ');
        var aFullRight = sFullRight.split(' ');

        // build out each word as a node
        for (var i = 0; i < aFullLeft.length; i++) {
            var sVal = aFullLeft[i];
            if (sVal != '') {
                $('<span> ' + sVal + ' </span>').appendTo($LeftWrap);
            }
        }
        for (var i = 0; i < aFullRight.length; i++) {
            var sVal = aFullRight[i];
            if (sVal != '') {
                $('<span> ' + sVal + ' </span>').appendTo($RightWrap);
            }
        }

        // reset text as full html words
        sFullLeft = $LeftWrap.html();
        sFullRight = $RightWrap.html();

        var fResize = function () {
            // reset closures for dynamic sizing
            $LeftWrap.html(sFullLeft);
            $CenterPrefix.html('').css('padding-left', 0);
            $CenterPhrase.html('&nbsp;' + sPhrase + '&nbsp;');
            $CenterSuffix.html('').css('padding-right', 0);
            $RightWrap.html(sFullRight);
            iParentWidth = $parent.innerWidth();

            // private variables
            var $leftWords = $LeftWrap.find('span');
            var $rightWords = $RightWrap.find('span');
            var iMaxWidthRemaining = (iParentWidth - $CenterPhrase.outerWidth());
            var iMaxSideWidth = Math.floor(iMaxWidthRemaining / 2);
            var iLeftRemaining = iMaxSideWidth;
            var iRightRemaining = iMaxSideWidth;
            var iCurrentWidth = iPhraseWidth;
            var iLeftIndex = $leftWords.size() - 1; // work backwards
            var iRightIndex = 0; // work forwards
            var iKerningTollerance = 2; // wraps too much sometimes

            // loop trackers
            var bKeepGoing = true;
            var bKeepGoingRight = true;
            var bKeepGoingLeft = true;

            // loop while there is still room for the next word
            while (bKeepGoing) {

                // check the left side
                if (bKeepGoingLeft) {
                    // get the next left word
                    var $nextLeft = $leftWords.eq(iLeftIndex);
                    var iLeftWordWidth = $nextLeft.outerWidth();
                    if (iLeftWordWidth < iLeftRemaining) {
                        // there's enough room.  add it.
                        $nextLeft.prependTo($CenterPrefix);
                        iLeftRemaining = iMaxSideWidth - $CenterPrefix.outerWidth();
                        iLeftIndex--;
                    } else {
                        // not enough room.  add remaining room as padding
                        bKeepGoingLeft = false;
                        $CenterPrefix.css('padding-left', (iLeftRemaining - iKerningTollerance));
                        iLeftRemaining = 0;
                    }
                }

                // check the right side
                if (bKeepGoingRight) {
                    // get the next right word
                    var $nextRight = $rightWords.eq(iRightIndex);
                    var iRightWordWidth = $nextRight.outerWidth();
                    if (iRightWordWidth < iRightRemaining) {
                        // there's enough room.  add it.
                        $nextRight.appendTo($CenterSuffix);
                        iRightRemaining = iMaxSideWidth - $CenterSuffix.outerWidth();
                        iRightIndex++;
                    } else {
                        // not enough room.  add remaining room as padding
                        bKeepGoingRight = false;
                        $CenterSuffix.css('padding-right', (iRightRemaining - iKerningTollerance));
                        iRightRemaining = 0;
                    }
                }

                // is there room left on either side?
                bKeepGoing = bKeepGoingLeft || bKeepGoingRight;
            }

            // calculate where to put the breaks.
            var iTempWidth = iParentWidth;
            while (iLeftIndex > 0) {
                var $word = $leftWords.eq(iLeftIndex);
                iTempWidth = iTempWidth - $word.outerWidth();
                // account for kerning inconsistencies
                if (iTempWidth <= (2 * iKerningTollerance)) {
                    $('<br />').insertAfter($word);
                    iTempWidth = iParentWidth;
                } else {
                    iLeftIndex--;
                }
            }

        };

        // initial state
        fResize();

        $(window).resize(fResize);
    }
});

});
Run Code Online (Sandbox Code Playgroud)

[更新要求的命名公约...... style ="居中":)]


Rya*_*yan 10

不幸的是,答案是你不能用HTML/CSS做你想要的.

要执行此操作,您需要设置一些宽度以强制文本中断到下一行,或者(最好)插入<BR>要在其中打破行的标记.HTML和/或CSS无法为您执行此操作.正如安德森在下面所说,如果需要,你将能够找到一种方法来使用JS.


Peb*_*bbl 3

将特定目标单词移动到单词允许的最佳水平中心

您可以使用非常简单的 JavaScript 实现粗略居中。它所做的就是沿着标记扫描,将它找到的第一个 TextNode 转换为用<span>s 包裹的“单词”,然后尝试插入换行符,直到找到最接近中心的目标单词。

在小提琴中,我用红色突出显示了代码认为应该在后面休息的跨度,用绿色突出显示了目标单词。在大多数情况下,它表现得很好,在某些情况下,您可能最终会在一行中出现一个单词——但是,这可以通过根据您的具体用例调整代码来解决。

以防万一人们没有意识到,这是可以实现的目标的说明,并且绝不是完美的 - 没有任何代码是完美的,因为它总是可以改进,而且应该如此。

小提琴

http://jsfiddle.net/s8XgJ/2/

更新的小提琴显示随机目标单词的行为:

http://jsfiddle.net/s8XgJ/3/

标记

<center>
  Once upon a time, there was a squirrel who lived in the 
  <span class="centered">middle</span> of the forest. I 
  say middle, but without knowing where the edges were, 
  the squirrel had no idea where the center was.
</center>
Run Code Online (Sandbox Code Playgroud)

我大致保留了您的标记,但是,正如其他人所说,您应该避免使用中心标签。我还将内部 div 转换为跨度以保留内联间距。如果这对您来说不可能,您仍然可以使用 div,您只需覆盖它的正常显示即可display: inline-block;

JavaScript / jQuery

jQuery.fn.findYourCenter = function( target ){
  base = $(this); target = base.children(target);
  base.contents().eq(0).each(function(){
    var i = -1, word, words, found, dif,
      last = Infinity,
      node = $(this), 
      text = node.text().split(/\s+/),
      cwidth = Math.round(target.width() * 0.5),
      bwidth = Math.round(base.width() * 0.5),
      breaks = 2 // code will try to insert 2 line breaks
    ;
    node.replaceWith(
      '<span class="word">'+text.join(' </span><span class="word">')+' </span>'
    );
    words = base.find('.word');
    do {
      while ( ++i < words.length ){
        word && word.removeClass('clear');
        word = words.eq(i).addClass('clear');
        dif = Math.round(Math.abs((target.position().left + cwidth) - bwidth));
        if ( dif < last ) { last = dif; found = i; }
      }
      word.removeClass('clear');
      if ( found ) {
        words.eq(found).addClass('clear');
        i = found; found = word = null;
      }
      else {
        break;
      }
    } while ( i < words.length && --breaks );
  });
};
Run Code Online (Sandbox Code Playgroud)

为了简洁起见,我使用了 jQuery。

CSS

您将需要这个 CSS 项目:

.clear:after {
  content: '';
  display: block;
  clear: both;
}
Run Code Online (Sandbox Code Playgroud)

如果您的.centered商品是<div>

.centered {
  display: inline-block;
}
Run Code Online (Sandbox Code Playgroud)

然后你需要执行的是:

jQuery(function($){
  $('center').findYourCenter('.centered');
});
Run Code Online (Sandbox Code Playgroud)


问题

为了让事情变得精确,你必须抵消一些东西——因为根据单词的长度(和位置),你不可能总是同时实现段落、行和目标单词的完美中心。上面的代码仍然保持行居中,但代价是目标单词被偏移。如果您想以行的代价使单词居中,您可以改进上述内容,对包含目标跨度的行进行边距修改。

目前,如果目标词出现在前五个词中,则不太可能实现居中,主要是因为该方法依赖于自动换行和换行。如果由于单词位于段落开头而无法使用两者,那么除了引入边距、填充或文本缩进之外,什么也做不了。

此代码依赖于能够<span>正确读取元素的位置。较旧的浏览器(例如 IE6 和 Safari/Opera 的早期版本)在这方面存在问题。

还有一件事需要注意。此代码依赖于浏览器在同一同步执行循环中立即重新计算其内部测量值。大多数现代浏览器似乎都会这样做(在大多数情况下),但是您可能会发现需要实施setTimeout(func, 0)setImmediate延迟才能使其在旧系统上运行。


...最后

这是一个相当疯狂的要求,到底是为了什么?:)