如何使字体大小相对于父级div?

60
我希望我的div中的文本按照与父级div的百分比比例保持相同的大小。 例如,我希望我的文本具有父级div宽度的50%的font-size。 因此,当页面大小变化时,文本始终以%相同的大小显示。

.counter-holder{
 display: block;
 position: absolute;
 width:90%;
 height:20%;
 top: 70%;
 left: 50%;
 /* bring your own prefixes */
 transform: translate(-50%, -50%);
}


.counter-element-box{
 position:relative;
 vertical-align: text-top;
 border-style: solid;
    border-width: 1px;
    width: 20%;
    height: 100%;
    float:left;
    margin: 6%;
}

.counter-element-text{
 position:absolute; 
 top:50%; 
 width: 50%;
 max-width:50%;
 display: inline-block;
 height:100%;
 margin-left:50%;
 font-size : 80%;overflow: hidden;
}

.counter-element-value{
 position:absolute; 
 top:50%; 
 width: 50%;
 max-width:50%;
 display: inline-block;
 height:100%;
 padding-left:30%;
 font-size : 80%;overflow: hidden;
}
<div class="counter-holder">
 <div class="counter-element-box">
  <div id="years" class="counter-element-value">
   0
  </div>
  <div class="counter-text counter-element-text" >
      Years
  </div> 
 </div>
 <div class="counter-element-box">
  <div id="missions" class="counter-element-value">
   0  
  </div>
  <div class="counter-text counter-element-text" >
      Missions
  </div>
 </div> 
 <div class="counter-element-box"> 
    <div id="team" class="counter-element-value">
      0 
    </div>
    <div class="counter-text counter-element-text" >
       Team
    </div>
 </div>       
</div>

在全屏中运行此片段,并尝试调整页面大小,查看文本大小如何更改并不适合div边界。 如何防止它发生,使其始终保持在边界内?


你确定要更改 font-size 而不是 width 吗? - Core972
我两种方法都尝试了,但并没有什么帮助。无论选择哪一种选项,文本仍然在调整大小。 - Tachi
在https://dev59.com/gWkv5IYBdhLWcg3w3Uk0上有一个类似的问题,有许多好的答案。 - Theophilus
10个回答

26

我解决这个问题的方法是使用JavaScript来测量容器的大小,然后在该容器上设置字体大小(以px为单位)。一旦为容器设置了基准线,所有内容的相对字体大小将使用em或百分比正确缩放。

我正在使用React:

<div style={{ fontSize: width / 12 }} >
  ...
</div>

CSS:

div {
  font-size: 2em;
}

我正在使用Angular,这对我很有帮助。 - Roshan Khandelwal
5
你能添加你所使用的JS代码来获取宽度吗? - ThomasRones
你可以使用window.screen来获取当前屏幕的详细信息,并使用任何你喜欢的宽度。 - Shahbaz Shaikh
6
12来自哪里? - Jack

13
你可以使用容器查询单位cqwcqhcqicqbcqmincqmax。它们被所有现代浏览器所支持。
这将允许调整font-size和其他属性不仅限于直接父级,还可以针对任何定义为容器的祖先,并在必要时也可以针对容器的垂直尺寸进行调整。

.container {
  /* Define a container */
  /* Use `inline-size` instead of `size` if you are only
     interested in inline size, which is horizontal
     for Latin and many other layouts. */
  container-type: size;
  
  /* Other styles */
  height: 3em;
  border: solid 2px;
  overflow: hidden;
}

.horizontal {
  resize: horizontal;
}

.vertical {
  resize: vertical;
}

.both {
  resize: both;
}

.horizontal .child {
  font-size: 10cqw;
}

.vertical .child {
  font-size: 30cqh;
}

.both .child {
  font-size: 30cqmin;
}
<div class="container horizontal">
  <div class="child">Resize me horizontally!</div>
</div>

<div class="container vertical">
  <div class="child">Resize<br>me<br>vertically!</div>
</div>

<div class="container both">
  <div class="child">Resize me<br>in all<br>ways!</div>
</div>


4
这真是个天赐之物,应该被接受为答案!几乎所有主流浏览器都支持它,除了IE,而且它使我的组件看起来非常好,无需像big-text.js这样的额外JavaScript框架。 - NessDan
这差不多是我想要的,但是我无法让它根据文本的数量和父容器的大小来实际减小字体大小。例如,如果你在“container horizontal” div中添加了很多字符但没有空格,它会溢出并无法调整文本大小以适应框内。 - Rontron

12
在CSS中无法以所要求的方式实现。字体大小只能以某些特定的方式设置,而任何百分比值都是相对于字体的大小而非块的宽度或高度。
因此,尽管这并未提供您的问题的解决方案,但这是回答CSS是否可以做到这一点的答案:不能。
这里有很多答案似乎回答了错误的问题,并推荐使用相对于视口而非父元素大小的vw单位。还有一些答案采用JavaScript,如果你不介意这种方法的话是可行的。然后是slaviboy的答案,提倡使用CSS用户变量,这是一种我钦佩的创造性解决方案,尽管它不能实现OP所要求的最终效果。
在许多情况下,当您想相对于父元素的宽度设置字体大小时,您已经拥有足够的信息来能够通过一些数学计算来实现:计算出父元素的宽度如何计算,然后看看您是否可以在字体大小设置中重用类似的计算。
例如,如果父元素的宽度是视口宽度或其已知百分比,则基于vw的答案将起作用,您只需计算出正确的比例即可。如果父元素的宽度是一些绝对值,如500px,则更容易。只有当父元素的宽度完全不可预测时,这将是困难的,尽管可以推测OP的情况正是如此。例如,如果父元素的宽度基于内容,并且内容可能由用户提交或其大小无法预测。

7
如果你想谈论响应式缩放,那么你可以实现它,但一切都取决于你想要实现什么。在下面的代码中,我创建了一个具有比例(高度/宽度=1/2)的div容器。当你改变浏览器窗口的大小时,容器和文本将会响应式缩放。根据窗口的大小,它将根据视口宽度(VW)和视口高度(VH)更改字体大小。要添加新的字体大小,你必须设置两次,一次根据-vw,另一次根据-vh。我使用了CSS变量(var),这样代码更易于理解。

Example

body {
    background-color: #000;
    padding: 0;
    margin:0;
}

/* position element in the middle */
.middle {
    position: absolute;
    top:50%;
    left: 50%;
    transform: translate(-50%, -50%);
} 


/* Ratio: height/width */ 
:root {
    --ratio: 0.5;
    --reverse-ratio: 2;
    --container-width: 50vw;
    --container-height: 50vh;

    --font1-sizeVW: 15vh;
    --font1-sizeVH: calc(var(--ratio) * 15vw);

    --font2-sizeVW: 6vh;
    --font2-sizeVH: calc(var(--ratio) * 6vw);
}

#container {

    background-color: pink;
    width: var(--container-width);
    height: calc(var(--ratio) * var(--container-width));

    max-width: calc(var(--reverse-ratio) * var(--container-height));  
    max-height: var(--container-height);
}

#span1 {
    font-size: var(--font1-sizeVW);   
}

#span2 {
    font-size: var(--font2-sizeVW);  
}

/* max-width: (reversRatio * 100vh) */
@media all and (max-width: 200vh) {  

    #container {
        background-color: green;
    }

    #span1 {  
        font-size: var(--font1-sizeVH); 
    } 

    #span2 {  
        font-size: var(--font2-sizeVH);
    } 
}
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <style>
    </style>
</head>
<body>
    <div id="container" class="middle">
        <span id="span1">Hello</span>
        <span id="span2">Hello again</span>
    </div>
</body>
</html>


9
这与 视口(viewport) 有关,而不是父元素。 - John
确保您的父元素大小也相对于视口。这样,您可以设置子元素和父元素之间的比例,当页面大小更改时,两个元素都保持其比例并响应缩放。 - slaviboy
@slaviboy 我觉得你上面的例子可能是我问题的解决方案,但不幸的是我缺少一些东西。 我有一个svg,它会在窗口调整大小时进行缩放,还有一些不会变化的div。 我希望它们一起缩放并保持它们的相对位置。 我尝试设置top属性,例如top: calc(var(--container-height) * 5%);,但没有成功。 有什么方法可以实现这一点吗? 另外,您能解释一下,在middle类中使用transform属性的目的是什么吗? 这是我正在尝试做的事情的示例.. https://stackblitz.com/edit/lock-resizing-divs-wsemvn - gothaf
我认为这是通过计算实现的。在我的情况下,我使用React,这更容易,但CSS变量提供了本地实现的方式。好答案! - Vladyn

1

我不知道这是否有用,可能只是垃圾。 这个想法是手动获取元素的宽度,并从中计算出字体大小。我使用了一些JavaScript,因为我不知道CSS变量是否支持数学运算。评论中的代码可以工作,但不是动态的。

const resize_ob = new ResizeObserver(function(entries) {

let rect = entries[0].contentRect;

let currWidth = rect.width;    


let fontSize = rect.width / 10;

/*    

let testDiv = document.querySelector("#test_div");
let testDivStyle = getComputedStyle(testDiv);
let testDivRawWidth = testDivStyle.getPropertyValue('width')
let fontSize = parseInt(testDivRawWidth .substring(0, testDivRawWidth .length - 2)) / 10;
*/

testDiv.style.setProperty('--fontSize', fontSize+"px");
})
div {
background-color: lightblue;

height: 75vh;
width: 75vh;

font-size: var(--fontSize, 15vh);

}
<div id="test_div">

testing just a thing...

</div>


0
一个更简单和纯CSS的解决方案是将父级Div的宽度设置为vw。
然后,使用calc() CSS函数将父级宽度乘以.5(50%)以实现所需的结果。

body {
  background-color: #F9F1F0;
  height:100vh;
  width:100vw;
}

.parent-div {
background-color: #FF7F50;
height:100vh;
width:50vw; /* The key here is selecting vw, as it is a relative measurement */
text-align: center;
}

.child-h1 {
font-size: calc(50vw * .5); /* We can then use the relative measurement here and calculate 50% of the div's width and translate that to font size */
}
<!DOCTYPE html>
<html lang="en">
<head></head>
<body>
<div class="parent-div">
<h1 class="child-h1">50</h1>
</div>
</body>
</html>


-3

我发现这个方法非常有效,而且简单易行:

font-size: min(3vh,1.7vw);

只需根据您的字体微调比例即可。

这是有效的,因为它将您视口的较短侧作为限制因素来调整字体大小。 您还可以在父级 div 上设置此选项,然后在其子元素中使用 em 单位引用它。

就像这样

.parent{
  font-size: min(3vh,1.7vw);
}
.child {
  font-size: 2.2em;
}
<div class="parent">
  <div class="child">
    <p>Hello there</p>
  </div>
</div>


1
你可以使用vmin(视口最小值)单位,而不是使用min()vmin是另一种像vwvh一样的单位,但它基于视口宽度和高度中较短的那个。 - thomasrutter
1
我的猜测是因为问题要求不同的东西 - OP想要一个文本字符串,并根据父元素的宽度调整文本大小。虽然您可以使用vw根据视点宽度调整文本大小,但无法根据父元素宽度进行调整。因此,我认为除非修改他们的方法,否则OP想要的东西是不可能的,正如大多数答案所建议的那样。但我认为它们被投票降低是因为它们没有提供完全符合OP要求的内容。 - thomasrutter

-5

您可以使用视口单位来随窗口大小调整大小。 100vw 是完整的窗口宽度,而 100vh 则是高度。

.resizable-text {
  font-size: 50vw;
}
<div class="resizable-text">
  Text
</div>


这是相对于视口而不是父元素的。 - DeoxyribonucleicAcid

-7

响应式字体大小/根据浏览器窗口调整文本大小

可以使用vw单位来设置文本大小,vw代表"视口宽度"。

这样,文本大小将随着浏览器窗口的大小而变化:

例如:

<div>
<h2 style="font-size:10vw;">Ganesh Pandey</h2>
</div>

调整浏览器窗口大小,查看文本大小如何缩放。


5
相对于视口而言,而不是父元素。 - John

-18

使用 font-size: x% 不是相对于父元素的宽度,而是相对于元素通常应该具有的字体大小。

因此,如果您的元素的父级设置了 font-size: 12px,则在元素中使用 font-size: 50% 意味着该元素具有 font-size6px

你需要使用 视窗百分比vw

例如:font-size: 2vw

.counter-holder{
 display: block;
 position: absolute;
 width:90%;
 height:20%;
 top: 70%;
 left: 50%;
 /* bring your own prefixes */
 transform: translate(-50%, -50%);
}


.counter-element-box{
 position:relative;
 vertical-align: text-top;
 border-style: solid;
    border-width: 1px;
    width: 20%;
    height: 100%;
    float:left;
    margin: 6%;
}

.counter-element-text{
 position:absolute; 
 top:50%; 
 display: inline-block;
 margin-left:40%;
 font-size : 2vw;overflow: hidden;
}

.counter-element-value{
 position:absolute; 
 top:50%; 
 width: 50%;
 max-width:50%;
 display: inline-block;
 height:100%;
 padding-left:30%;
 font-size : 2vw;overflow: hidden;
}
<div class="counter-holder">
   
   <div class="counter-element-box">
    <div id="years" class="counter-element-value">
     0
       </div>
       <div class="counter-text counter-element-text" >
        Years
       </div> 
      </div>
      <div class="counter-element-box">
       <div id="missions" class="counter-element-value">
     0  
       </div>
       <div class="counter-text counter-element-text" >
        Missions
       </div>
      </div> 
      <div class="counter-element-box"> 
       <div id="team" class="counter-element-value">
     0 
       </div>
       <div class="counter-text counter-element-text" >
        Team
       </div>
      </div>       
</div>


很好的解释,之前从未听说过vw - Tachi
119
vwvh不是指父级元素的大小,而是指视口窗口的大小,对吧? - bryan
19
确实,这个答案不应该被标记为有效!我猜你需要一些JavaScript来相对于父元素调整文本大小,但视口单位绝对不是实现这一点的方式。 - MrMerrick
完全同意 - 我无法想象在实际情况下需要文本大小与浏览器视口大小相关的情况。更常见的情况是文本大小应该相对于父块的大小。其中一种解决方案是使用类似于 https://github.com/davatron5000/FitText.js 的 JavaScript。 - Serg
1
我有一个非常好的使用案例 - 我有一个元素,可以由管理员进行配置,以在普通用户页面上显示。对于用户来说,这个元素是屏幕的宽度,使用vw和vh进行缩放效果很好。我希望管理员能够拥有一个较小的预览,可能是页面宽度的某个可变比例,例如6个引导列,在中等断点时响应式地切换到全宽度。在此处,按包含框的宽度的百分比进行缩放将是理想的。 - stephan.com

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