동적 문자 수에 따라 글꼴 크기를 반응 적으로 만드는 순수 CSS


298

나는 이것이 자바 스크립트로 상당히 쉽게 해결할 수 있다는 것을 알고 있지만 순수한 CSS 솔루션에만 관심이 있습니다.

텍스트가 항상 고정 된 div에 맞도록 동적으로 텍스트 크기를 조정하는 방법을 원합니다. 다음은 샘플 마크 업입니다.

<div style="width: 200px; height: 1em; overflow: hidden;">
  <p>Some sample dynamic amount of text here</p>
</div>

컨테이너의 너비를 ems로 지정하고 글꼴 크기를 가져와 해당 값을 상속하면 이것이 가능할 수 있다고 생각했습니다.


1
와우 widthin em의 지정은 다른 방향으로 진행됩니다. 에 width따라 다릅니다 font-size. @JosephSilber 정확히 내가 생각한 것입니다.
Ana

1
이 질문이 궁금합니다. 간단한 자바 스크립트 함수를 작성하는 대신 순수한 CSS 솔루션을 사용하는 드라이브는 무엇입니까?
Austin Mullins

22
드라이브는 단순히 문제가 존재하고 순수한 CSS 솔루션이 놀랍기 때문입니다. 몇 가지 스타일 만 적용 할 수있는 가능성과 동적 콘텐츠가 디자인을 훼손하지 않을 것이라는 점을 생각하십시오.
DMTintner


2
fitText에는 한계가 있습니다. 예를 들어 너비가 500px 이상인 작은 화면에서만 실행하고 싶습니다. 제목이 더 이상 터지는 것을 원하지 않습니다. 더 많은 JavaScript를 작성해야합니다. 레이아웃을 위해 JavaScript를 사용하면 관심사 분리가 매우 빠르게 분류됩니다. 절대 빠른 라이너가 아닙니다.
Costa

답변:


513

방금 VW 장치를 사용하여 이것이 가능하다는 것을 알았습니다. 뷰포트 너비 설정과 관련된 단위입니다. 레거시 브라우저 지원 부족과 같은 몇 가지 단점이 있지만 사용을 진지하게 고려해야 할 사항입니다. 또한 다음과 같이 이전 브라우저에 대체를 제공 할 수 있습니다.

p {
    font-size: 30px;
    font-size: 3.5vw;
}

http://css-tricks.com/viewport-sized-typography/https://medium.com/design-ux/66bddb327bb1


30
이것을 위해 2 개의 ups를 줄 것입니다. 승리를위한 CSS 솔루션!
Mihkel L.

34
전문가 팁 : 텍스트가 너무 작아지는 것을 방지하고 font-size:calc(100% + 2vw);이와 비슷한 작업을 통해 제어권을 다시 얻을 수 있습니다 . 좀 그렇습니다 min-font-size. 에 대한 브라우저 지원은와 calc유사합니다 vw.
Prinzhorn

116
불쾌감을 주었지만 지금은 이것이 원래의 질문에 실제로 대답하는지 궁금합니다. 이해하는 것은 텍스트 길이가 동적이며 항상 너비 div(200px)에 맞게 글꼴 크기를 변경하고 싶다는 것 입니다. 이 문제를 어떻게 해결합니까?
Floremin

26
@Floremin의 정서에 동의합니다. 텍스트 너비 / 높이의 컨테이너가 아닌 뷰포트 너비 / 높이를 기준으로 모든 글꼴 크기를 조정합니다.
MickJuice

24
@Floremin이 맞습니다.이 질문은 다루지 않습니다. 이것은 폰트 크기를 컨테이너 너비와 관련하여 문자열 길이의 함수가 아닌 컨테이너 너비의 함수로 계산합니다.
Henry

113

CSS3 는 뷰 포트와 관련된 새로운 차원을 지원합니다. 그러나 이것은 안드로이드 <4.4에서 작동하지 않습니다

  1. 3.2vw = 뷰포트 너비의 3.2 %
  2. 3.2vh = 뷰포트 높이의 3.2 %
  3. 3.2vmin = 더 작은 3.2vw 또는 3.2vh
  4. 3.2vmax = 더 큰 3.2vw 또는 3.2vh

    body
    {
        font-size: 3.2vw;
    }

css-tricks.com / ....caniuse.com / ...을 참조하십시오 .

또는

미디어 쿼리 사용. 가장 간단한 방법은 치수를 % 또는 em로 사용하는 것입니다. 기본 글꼴 크기 만 변경하면 모든 것이 변경됩니다.

@media (max-width: @screen-xs) {
    body{font-size: 10px;}
}

@media (max-width: @screen-sm) {
    body{font-size: 14px;}
}


h5{
    font-size: 1.4em;
}

치수를 % 또는 em로 사용하십시오 . 기본 글꼴 크기 만 변경하면 모든 것이 변경됩니다. 이전 버전에서는 매번 h1이 아닌 body 글꼴을 변경하거나 기본 글꼴 크기를 장치의 기본값으로 설정하고 모두 em

em, px 및 %에 대한 자세한 내용은 kyleschaeffer.com / .... 을 참조하십시오 .


12
질문은 전체 뷰포트가 아닌 컨테이너를 기준으로 한 스케일링에 관한 것입니다.
Arnaud Weil

6
... 그리고 질문은 글자 수에 따른 스케일링에 관한 것입니다
Bravo


14

유일한 방법은 다른 화면 크기에 대해 다른 너비를 설정하는 것이지만이 방법은 매우 정확하지 않으므로 js 솔루션을 사용해야합니다.

h1 {
    font-size: 20px;
}

@media all and (max-device-width: 720px){
    h1 {
        font-size: 18px;
    }
}

@media all and (max-device-width: 640px){
    h1 {
        font-size: 16px;
    }
}

@media all and (max-device-width: 320px){
    h1 {
        font-size: 12px;
    }
}

12

나는 오랫동안 죽은 질문을 부활시키고 있다는 것을 알고 있지만 같은 질문이 있었고 무언가를 추가하고 싶었습니다. 이것을 금지하지 마십시오.이 답변을 정당화하는 것이 중요하다고 생각했습니다. 필요한 경우 삭제하겠습니다. @Joseph Silber는 잘못되었습니다. 실제로 모든 가능성을 코딩하는 것이 실제로 가능한 방법입니다. 그 이유는 실제로 무한한 가능성이 없기 때문입니다. 기술적으로는 있지만 방문자의 99 %가 표준 해상도를 사용합니다. 대부분의 모바일 OS가 창 크기를 조정하지 않고 전체 화면으로 앱을 실행하기 때문에 모바일 (응답 성 웹 디자인의 주된 이유)의 경우에는이 점이 사실입니다.

또한 스크롤 막대로 인해 높이는 거의 관련이 없습니다 (1, 4, 5 피트 이상인 웹 페이지는 즉시 떠날 수 있지만 대부분은 사실입니다). 너비 만 걱정하면됩니다. 그리고 실제로 코딩해야 할 폭은 240, 320, 480 (이전 iThings의 경우), 640, 800, 1024, 1280, 1440, 1600, 1920, 2048, 2560입니다. 4k, 이미지가 너무 부풀어 오르고 100 % 너비로 늘어난 2560 크기가 4k 모니터에서 잘 보입니다 (테스트했습니다). 또한 이전 포스터가 제안한대로 720 (720x480)을 신경 쓰지 마십시오. 디지털 카메라에서 거의 독점적으로 사용되는 해상도이며 매우 드문 경우입니다.

누군가가 이국적인 해상도를 사용하고 있다면 지난 15 년 동안 만들어진 거의 모든 렌더러가 반올림되므로 누군가의 화면 너비가 맞다면 말입니다. 1100, 1024 CSS 규칙을로드 할 예정이므로 사이트가 중단되지 않아야합니다. 이것은 반응 형 규칙을 불필요하게 만들려고 시도하여 이국적인 해상도를 설명합니다. 웹 브라우저를 너무 오래 사용하여 사이트를로드하지 않는 한 모든 가능한 설정을 픽셀 단위로 코딩해야한다는 생각은 어리 석습니다. 어쨌든.


1
그리고 이제 iPhone 6 / 6 +의 경우 375 및 414 :-/
yar1

SASS 또는 Compass를 사용하고 기능을 수행하는 경우 훨씬 더 쉬워집니다. 함수는 모든 CSS가 당신을 위해 일할 수 있습니다. 한 번만 쓸 많은 것.
cjbarth

높이가 기기를 측면으로 90º 돌리기 전까지는 거의 관련이 없습니다.
Carvo Loco

이것은 컨테이너의 너비와 아무 관련이 없습니다-쉽게 무한한 가능성이 있습니다.
mcheah

8

참고로 비 CSS 솔루션 :

아래는 컨테이너 내의 텍스트 길이에 따라 글꼴 크기를 조정하는 일부 JS입니다.

약간 수정 된 코드가 있지만 다음과 같은 아이디어가있는 코드 :

function scaleFontSize(element) {
    var container = document.getElementById(element);

    // Reset font-size to 100% to begin
    container.style.fontSize = "100%";

    // Check if the text is wider than its container,
    // if so then reduce font-size
    if (container.scrollWidth > container.clientWidth) {
        container.style.fontSize = "70%";
    }
}

나를 위해 사용자가 드롭 다운에서 선택하면 메뉴의 div가 채워집니다 (이곳에서 동적 텍스트가 발생합니다).

    scaleFontSize("my_container_div");

또한 CSS 줄임표 ( "...")를 사용하여 더 긴 텍스트도 자릅니다 .

#my_container_div {
    width: 200px; /* width required for text-overflow to work */
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

따라서 궁극적으로 :

  • 짧은 텍스트 : 예 : "APPLES"

    완전히 렌더링되고 멋진 큰 글자.

  • 긴 텍스트 : 예 : "애플 및 오렌지"

    위의 JS 스케일링 기능을 통해 70 % 축소됩니다.

  • 매우 긴 텍스트 : 예 : "APPLES & ORANGES & BANAN ..."

    CSS 규칙과 함께 위의 JS 스케일링 기능을 통해 70 % 축소되고 "..."타원으로 잘립니다.

CSS 글자 간격을 사용하여 텍스트를 좁히면서 동일한 글꼴 크기를 유지하면서 탐색 할 수도 있습니다.


사용자로 부결 순수 CSS 솔루션을 요구 한
AnotherLongUsername

2

많은 사람들이 @DMTinter의 게시물에 대한 의견에서 언급했듯이 OP는 문자 수 ( "양")에 대해 묻고있었습니다. 그는 CSS에 대해서도 질문했지만 @Alexander가 지적했듯이 "CSS로는 불가능합니다". 내가 알 수있는 한, 그것은 현재로서는 사실처럼 보이므로 사람들이 다음으로 가장 좋은 것을 알고 싶어하는 것이 논리적으로 보입니다.

나는 이것을 자랑스럽게 생각하지 않지만 작동합니다. 그것을 달성하기 위해 과도한 양의 코드처럼 보입니다. 이것이 핵심입니다 :

function fitText(el){
  var text = el.text();
  var fsize = parseInt(el.css('font-size'));
  var measured = measureText(text, fsize);

  if (measured.width > el.width()){
    console.log('reducing');
    while(true){
      fsize = parseInt(el.css('font-size'));
      var m = measureText(text, fsize );
      if(m.width > el.width()){
        el.css('font-size', --fsize + 'px');
      }
      else{
        break;
      }
    }
  }
  else if (measured.width < el.width()){
    console.log('increasing');
    while(true){
      fsize = parseInt(el.css('font-size'));
      var m = measureText(text, fsize);
      if(m.width < el.width()-4){ // not sure why -4 is needed (often)
        el.css('font-size', ++fsize + 'px');
      }
      else{
        break;
      }
    }
  }
}

여기 JS 빈은 다음과 같습니다 http://jsbin.com/pidavon/edit?html,css,js,console,output
(정말 텍스트를 측정하기 위해 캔버스를 사용에 관심이 아니에요 그것은 가능한 개선을 제안하십시오 ... 보인다 너무 많은 오버 헤드 (?)를 좋아하십시오.

measureText 함수를위한 @Pete에게 감사합니다 : https://stackoverflow.com/a/4032497/442665


2

이 솔루션은 또한 도움이 될 수 있습니다.

$(document).ready(function () {
    $(window).resize(function() {
        if ($(window).width() < 600) {
            $('body').css('font-size', '2.8vw' );
        } else if ($(window).width() >= 600 && $(window).width() < 750) {
            $('body').css('font-size', '2.4vw');
        } 
         // and so on... (according to our needs)
        } else if ($(window).width() >= 1200) {
            $('body').css('font-size', '1.2vw');
        }
    }); 
  });

그것은 나를 위해 잘 작동했습니다!


이것이 자동 줄 바꿈을 어떻게 고려합니까?
Leif Neland


2
calc(42px + (60 - 42) * (100vw - 768px) / (1440 - 768));

이 방정식을 사용하십시오.

1440 및 768보다 크거나 작은 경우 정적 값을 지정하거나 동일한 방법을 적용 할 수 있습니다.

vw 솔루션의 단점은 스케일 비율을 설정할 수 없다는 것입니다. 화면 해상도 1440에서 5vw가 60px 글꼴 크기, 아이디어 글꼴 크기로 끝날 수 있지만 창 너비를 768로 줄이면 끝날 수 있습니다. 원하는 최소값이 아닌 12px입니다. 이 방법을 사용하면 상한과 하한을 설정할 수 있으며 글꼴은 그 사이에서 확장됩니다.


-2

안의 문자열 길이를 기반으로 글꼴 크기를 계산하는 조회 테이블을 만듭니다 <div>.

const fontSizeLookupTable = () => {
  // lookup table looks like: [ '72px', ..., '32px', ..., '16px', ..., ]
  let a = [];
  // adjust this based on how many characters you expect in your <div>
  a.length = 32;
  // adjust the following ranges empirically
  a.fill( '72px' ,     );
  a.fill( '32px' , 4 , );
  a.fill( '16px' , 8 , );
  // add more ranges as necessary
  return a;
}

const computeFontSize = stringLength => {
  const table = fontSizeLookupTable();
  return stringLength < table.length ? table[stringLength] : '16px';
}

경험적 테스트를 통해 모든 매개 변수를 조정하고 조정하십시오.


매개 변수에 대한 경험적 테스트는 본질적으로 시간 복잡성을 가진 이진 검색입니다 : O (log n).
그것에 대해 생각해 보자

실제로이 함수를 호출하는 것을 잊었습니다. 또한 속성으로 배열 길이에 액세스해야합니다.
lukk

@lukk : 피드백 주셔서 감사합니다. 지금 고쳤습니다.
그것에 대해 생각해 보자
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.