将文本拉伸以适应div宽度

75

我有一个固定宽度的 div,但是 div 内部的文本可能会变化。

是否有一种方式,通过 CSS 或其他方式,设置字母之间的间距,使文本始终完美地填充 div?


你想要改变“字母间距”(如letter-spacing)还是字体大小?编辑:或者像@SmudgerDan的答案一样,是指单词之间的间距 - thirtydot
间距和字体大小可以调整以确保块格式。 - Curtis
1
为什么不使用text-align:justify? - George Katsanos
@GeorgeKatsanos 我发现"text-align:justify"并不总是正确地填充区域。例如,如果我有一个宽度为300px的div,其中包含文本内容"Lorem Ipsum",这并不能拉伸以填充该区域。 - Curtis
@Curt,text-align:justify可以使用。请看下面的答案。 - A F
13个回答

45

这可以通过使用 text-align: justify 和一个小hack来完成。这里可以看到:

div{
  background-color:gold;
  text-align:justify;
}

span{
  background-color:red;
  width:100%;
  height:1em;
  display:inline-block;
}
<div>
  Lorem ipsum sit dolor
  <span> </span>
</div>

是在文字后面添加一个假的单词元素,这个假单词实际上是一个带有display:inline-blockwidth:100%属性的元素。

在我的例子中,这个假单词是红色的,并且设置了1em的高度,但即使没有设置高度,这个技巧也可以使用。


5
这个方案在我们想要均等地分割单词时非常有效,但我希望能够均等地分离字母。有没有办法调整这个脚本来实现这一点? - Curtis
不确定您所说的“平均分隔字母”的意思。您是指每个字母应该均匀分隔,而不考虑空格吗? - A F
6
+1 魔法值得赞赏,甚至可以使用 :after 选择器来改进,而不是使用 span 元素。 - schellmax
@schellmax 你是什么意思? - Taylor C. White
4
他的意思是这是一个与他所问的问题不同的解决方案。他所问的是如何将一个“单词”分隔开以填充容器,而不是多个单词。字距与词距。当然,该解决方案也适用于单词 - 但是通过间隔每个字母,而不是每个单词。如果只有一个单词,则您的解决方案无效。 - Peter Kionga-Kamau

39

正如Mark所说,text-align:justify;是最简单的解决方案。然而,对于短文本,它没有任何效果。以下jQuery代码将文本拉伸到容器的宽度。

它计算每个字符的空间,并相应地设置letter-spacing,使文本拉伸到容器的宽度

如果文本太长无法适应容器,则让其扩展到下一行,并将text-align:justify;设置为文本。

这里是演示:

$.fn.strech_text = function(){
    var elmt          = $(this),
        cont_width    = elmt.width(),
        txt           = elmt.html(),
        one_line      = $('<span class="stretch_it">' + txt + '</span>'),
        nb_char       = elmt.text().length,
        spacing       = cont_width/nb_char,
        txt_width;
    
    elmt.html(one_line);
    txt_width = one_line.width();
    
    if (txt_width < cont_width){
        var  char_width     = txt_width/nb_char,
             ltr_spacing    = spacing - char_width + (spacing - char_width)/nb_char ; 
  
        one_line.css({'letter-spacing': ltr_spacing});
    } else {
        one_line.contents().unwrap();
        elmt.addClass('justify');
    }
};


$(document).ready(function () {
    $('.stretch').each(function(){
        $(this).strech_text();
    });
});
p { width:300px; padding: 10px 0;background:gold;}
a{text-decoration:none;}

.stretch_it{ white-space: nowrap; }
.justify{ text-align:justify; }

.one{font-size:10px;}
.two{font-size:20px;}
.three{font-size:30px;}
.four{font-size:40px;}
.arial{font-family:arial;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p class="stretch one">Stretch me</p>
<p class="stretch two">Stretch me</p>
<p class="stretch three">Stretch <a href="#">link</a></p>
<p class="stretch two">I am too slong, an I would look ugly if I was displayed on one line so let me expand to several lines and justify me.</p>
<p  class="stretch arial one">Stretch me</p>
<p class="stretch arial three">Stretch me</p>
<p class="stretch arial four">Stretch me</p>
<p class="arial two">Don't stretch me</p>

Js fiddle 演示


你好,我该如何去除文本的上下内边距? - Asme Just
5
这对我非常有用,我做了一些更改以使其具有响应性:http://jsfiddle.net/DPRr9/347/。 - Elaine Marley
@zeleniy 不错! - web-tiki

9

更简单的HTML/CSS方法是使用flexbox。

它也可以立即响应。但请注意,如果将其用作h1或其他内容,SEO将无法捕捉到它。

<div class="wrapper">
<div>H</div>
<div>e</div>
<div>l</div>
<div>l</div>
<div>o</div>
<div>&nbsp</div>
<div>W</div>
<div>o</div>
<div>r</div>
<div>l</div>
<div>d</div>

CSS:

.wrapper{
  width: 100%;
  text-align: center;
  display: flex;
  flex-flow: row nowrap;
  justify-content: space-between;
  border: 1px solid black;
}

这里是jsfiddle


3
2016年最佳解决方案(仅代表个人意见) - mothmonsterman
2
使用flex布局会更容易一些.. 在包装器div上使用fxLayout="row" fxLayoutAlign="space-evenly center" - umutesen
非常好的想法,可以预先了解文本,并且只需少量的 javascript 代码,它也可以与动态文本一起使用。 - user12163165

7
也许这可以帮助你:
text-align:justify;

1
这是一些示例文本供您尝试: <div style="font:normal 12px Arial; width:200px;">二月</div> - Peter Kionga-Kamau

6

我找到了一种更好的解决方案来处理短于一行的文本,而不需要额外的 JavaScript 或标签,只需一个类。

.stretch{ 
  /* We got 2rem to stretch */
  width: 5rem;
  /* We know we only got one line */
  height: 1rem;
  
  text-align: justify; 
}
.stretch:after{
    /* used to stretch word */
    content: '';
    width: 100%;
    display: inline-block; 
}
<div class="stretch">你好么</div>
<div class="stretch">你好</div>


1
@Shammoo 我运行了这段代码片段,它按预期工作,你测试过这个片段吗? - wener
你从哪里得到了5rem?为什么要选择竖排字体? - AlxVallejo

5

有点晚来的派对,但是要实现简单、纯CSS的效果,可以考虑使用flexbox

h1.stretch {
  display: flex;
  flex-direction: row;
  justify-content: space-between;
}
<h1 class="stretch">
  <span>F</span>
  <span>o</span>
  <span>o</span>
  <span>B</span>
  <span>a</span>
  <span>r</span>
</h1>

不确定是否将每个字母包含在标签内(注意,任何元素都可以)会影响SEO,但我想搜索引擎会从用于重要标记(如标题)的标签的innerHTML中剥离标签。(有了解SEO的人来确认吗?)


这个确切的方法已经由Nathan在2015年11月1日回答过了。 - Davbog

4

以上一些答案都有效,但文本必须与许多子div换行,并且有很多额外的代码。
div内部的文本应该是干净的,所以我用JS编写了它。

   const words = document.querySelector(".words");
words.innerHTML = words.innerText.split("").map(e => !e.trim() ? "<div>&nbsp</div>" : `<div>${e}</div>`).join("");
.words {
  width: 100%;
  display: flex;
  flex-flow: row nowrap;
  justify-content: space-between;
}
<div class="words">This is the demo text</div>


我喜欢它。可以写得更短一些:.map(e => !e.trim() ? "<div>&nbsp</div>" : \<div>${e}</div>`);` - Bram Vanroy

3

2018年3月 如果您在更加现代的时代遇到这个问题...

我试图按照原帖子所要求的只用一个单词,以下是我成功实现的方法:

1. 使用 <span> 并设置css: span { letter-spacing: 0px; display:block} (这使元素只有单词长度宽度)

2. 在加载时捕获 span 的宽度 let width = $('span').width();

3. 捕获 span 的长度 let length = $('span').length;

4. 将 span 的宽度重置为容器的宽度 $('span').css({'width','100%'});

5. 捕获 span 的新宽度 (或者直接使用容器宽度) let con = $('span').width();

6. 计算并设置字间距以填满容器 $('span').css({'letter-spacing':(cont-width)/length})

显然,这可以转换为使用纯js,并且即使与大多数字体样式(包括非等宽字体)一起使用也很有用。


1
我尝试在jsfiddle上实现它,但似乎不起作用。 - user1063287

1

因此,如果您将wener的拉伸短文本行的答案与另一个线程中的使用真实元素的建议相结合,您可以在不需要:after伪类的情况下完成整个过程。

您将实际元素替换并将其放置在要对齐的元素之后。这将以相同的方式触发对齐。

header {
  background-color: #ace;
  text-align: justify;
}

.hack {
  display: inline-block;
  width: 100%;
}
<header>
  <div>
    A line of text to justify
    <div class="hack"></div>
  </div>
</header>

这种变化让你可以在React和样式对象中使用这个技巧:

const style = {
  backgroundColor: '#ace',
  textAlign: 'justify'
};

const hack = {
  display: 'inline-block',
  width: '100%'
};

const example = (
  <header style={ style }>
    <div>
      A line of words to stretch
      <div style={ hack } />
    </div>
  </header>
);

ReactDOM.render(example, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>

<div id="root"></div>

这已经够丑陋和笨拙了,但从那里开始,您必须选择您想要“修复”容器多余高度的方式:固定高度或使用容器的负边距?相对定位和来自后续元素的重叠?将容器背景与页面背景匹配,并假装那个额外的边距是有意的?

@VisionHive 这并不是它的本意。它只是用CSS解决了单词对齐的问题,而没有使用伪元素,这样你就可以使用CSS对象。请参见这个更完整的解决方案 - worc
是的,看起来那个链接是唯一的方法(没有本地CSS方法)。哎呀。 - Peter Kionga-Kamau

1
如果有人想要了解如何对齐内容并仅居中最后一行,可以使用以下代码:
text-align: justify;
text-align-last: center;

看例子:

见下面的示例:

.custom-justify{
   text-align: justify;
   text-align-last: center;
   padding: 0 10px 0 10px;
}
<div class="custom-justify">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis mollis elementum bibendum. Cras pellentesque sed augue nec lacinia. Duis at eros vel lorem cursus laoreet ac vel justo. Maecenas ornare, ligula ut porttitor sollicitudin, turpis urna auctor ipsum, a consectetur felis nibh vel est. Nullam id lorem sit amet magna mollis iaculis eu vitae mauris. Morbi tempor ut eros ut vulputate. Quisque eget odio velit. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Sed posuere enim tellus, ut vestibulum libero dapibus ac. Nulla bibendum sapien non luctus vehicula. Aenean feugiat neque nunc, in fermentum augue posuere vel. Maecenas vitae diam in diam aliquet aliquam.<div>


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接