CSS의 모든 텍스트를 세로로 정렬하는 방법은 무엇입니까?


12

문제는 같은 그 특정 문자 것 같다 g, y, q슬로프 아래가 수직 중심을 허용하지 않는 것이 꼬리가 등. 다음은 문제를 보여주는 이미지 ㅏ입니다.

녹색 상자의 문자는 아래쪽 꼬리가 없으므로 기본적으로 완벽합니다. 빨간색 상자에있는 것은 문제를 보여줍니다.

모든 문자가 완벽하게 수직으로 가운데에 오게하고 싶습니다. 이미지에서 아래쪽 꼬리가있는 문자는 세로 중앙에 있지 않습니다. 이것이 교정 할 수 있습니까?

여기에 문제를 완전히 보여주는 바이올린이 있습니다.

.avatar {
    border-radius: 50%;
    display: inline-block;
    text-align: center;
    width: 125px;
    height: 125px;
    font-size: 60px;
    background-color: rgb(81, 75, 93);
    font-family: "Segoe UI";
    margin-bottom: 10px;
}

.character {
    position: relative;
    top: 50%;
    transform: translateY(-50%);
    line-height: 100%;
    color: #fff;
}
<div class="avatar">
  <div class="character">W</div>
</div>

<div class="avatar">
  <div class="character">y</div>
</div>


1
이것은 흥미로운 질문입니다. 대답은 여기에 있습니다 : iamvdo.me/en/blog/…
dwjohnston

2
이 경우 중심 이 무엇인지 정의해야합니다 . 나를 위해 y 는 실제로 중심에 있고 A 는 그렇지 않을 수도 있습니다. 우리가 다른 글꼴 - 가족이있을 때의이 정렬이 더 악화 얻을 것이다 이야기하지 말자
Temani Afif

1
바로 글자가 작동하는 방식입니다. v에서 yo부분 g은 대문자의 가장 낮은 점과 같은 줄에 있기 때문에 정렬 됩니다. 당신의 논리, Å, Ä, Ö는 A와 O로 정렬되지만 그렇게 할 수는 없습니다. 그것에 대해 특별한 것을하고 싶다면 javascript를 사용하여 작은 대문자인지 확인한 다음 문자를 몇 문자 위로 조금씩 움직여야합니다.
Rickard Elimää

1
유용한 답변이 있는지 궁금합니다. 문제는 이것들이 진정으로 중심에 있다는 것입니다. 즉. y와 g를 위로 움직일 수 있다고하면 소문자 a가 있다면 어떨까요? 어떻게 표시해야합니까?
dwjohnston

2
글꼴 편집기에서 글꼴을 엽니 다. "중심"으로 표시 될 때까지 모든 문자를 편집하십시오 . 새로운 글꼴 모음으로 저장하고 사용하십시오. 15 분 이상 걸리지 않아야합니다. 나는 canvas 또는 co. 그러나 나는이 질문에 대해 생각할 것입니다.
Roko C. Buljan

답변:


4

다음은 JS를 사용하는 솔루션입니다. 아이디어는 데이터를 픽셀로 가져 오기 위해 요소를 이미지로 변환 한 다음 반복하여 각 문자의 위와 아래를 찾고 정렬을 수정하기 위해 변환을 적용하는 것입니다. 동적 글꼴 속성에서 작동합니다.

코드는 최적화되지 않았지만 주요 아이디어를 강조합니다.

최신 정보

다음은 코드의 첫 번째 최적화입니다.

var elems = document.querySelectorAll(".avatar");
var k = 0;

for (var i = 0; i < elems.length; i++) {
  domtoimage.toPixelData(elems[i])
    .then(function(im) {
     var l = im.length;
      /* Search for the top limit */
      var t = 0;
      for (var j = 0; j < l; j+=4) {
          if (im[j+1] == 255) { /* Since we know the colors, we can only test the G composant */
            t = Math.ceil((j/4)/125);
            break;
          }
      }
      /* Search the bottom limit*/
      var b = 0;
      for (var j = l - 1; j >= 0; j-=4) {
          if (im[j+1] == 255) {
            b = 125 - Math.ceil((j/4)/125);
            break;
          }
      }
      /* get the difference and apply a translation*/
      elems[k].querySelector('.character').style.transform = "translateY(" + (b - t)/2 + "px)";
      k++;
    });
}
.avatar {
  border-radius: 50%;
  display: inline-flex;
  vertical-align:top;
  justify-content: center;
  align-items: center;
  width: 125px;
  height: 125px;
  font-size: 60px;
  background: 
    linear-gradient(red,red) center/100% 1px no-repeat,
    rgb(81, 75, 93);
  font-family: "Segoe UI";
  margin-bottom: 10px;
}

.character {
  color: #fff;
}
<script type="text/javascript" src="https://css-challenges.com/wp-content/themes/ronneby_child/js/dom-to-image.js"></script>
<div class="avatar">
  <div class="character">W</div>
</div>

<div class="avatar">
  <div class="character">y</div>
</div>

<div class="avatar">
  <div class="character" style="font-size:35px">a</div>
</div>

<div class="avatar">
  <div class="character" style="font-size:25px">2</div>
</div>
<div class="avatar">
  <div class="character">o</div>
</div>
<div class="avatar">
  <div class="character">|</div>
</div>
<div class="avatar">
  <div class="character">@</div>
</div>
<div class="avatar">
  <div class="character">Â</div>
</div>

<div class="avatar">
  <div class="character" style="font-family:arial">Q</div>
</div>
<div class="avatar">
  <div class="character">~</div>
</div>
<div class="avatar">
  <div class="character">8</div>
</div>

<div class="avatar">
  <div class="character">ä</div>
</div>
<div class="avatar">
  <div class="character">ç</div>
</div>

<div class="avatar">
  <div class="character">$</div>
</div>

<div class="avatar">
  <div class="character">></div>
</div>
<div class="avatar">
  <div class="character">%</div>
</div>

이것을 위해 dom-to-image 플러그인을 사용하고 있습니다.


느리게 진드기 진드기이지만 이것은 지금까지 지속적으로 작동하는 최초의 솔루션입니다. (기술적으로 중심 Â 이상하게 보이는 것을주의와.)
Brilliand

@Brilliand 나는 명시 적으로 사용 Â나는 그의 대답에 댓글로 자신의 중심이 최적이 아닌 것을 보여주기 위해) 그는 아마이를보고 난 후에 그의 마음을 변경하고 방법 글꼴 작품을 받아 들일 것
Temani Afif을

이것은 꽤 좋아 보인다. 더 효율적으로 만들 수 있다면 이것을 사용할 것이라고 생각합니다. 현재 조금 느립니다.
크로네 가방

@ChronBag 예 코드를 작업하고 최적화 할 수 있습니다. 여기에 대한 여지가 있습니다. 나는 많은 시간이 걸리고 실제로 질문의 목적이 아니기 때문에 그것을하지 않았다. 나는 주요 아이디어에 집중하고 싶었다. 아마 나중에 할 것입니다.
Temani Afif

@ChronBag는 조금 더 빠른 최적화를 추가했습니다.
Temani Afif

1

더 나은 대답이있을 수 있지만 유일한 방법은 다음 중 하나인지 여부에 따라 다른 스타일을 수동으로 적용하는 것 같습니다.

  • 대문자
  • 꼬리가있는 소문자
  • 스토킹이있는 소문자
  • 둘 다없는 소문자

내 이해에 따르면, 내가 생각하는 꼬리와 줄기의 상대 높이는 글꼴에 의해 정의됩니다. 프로그래밍 방식으로 액세스 할 수있는 방법이 있는지 확실하지 않으므로 글꼴 로이 값을 조정해야 할 수도 있습니다.

또한이 솔루션은 여러 언어를 지원하는 데 적합하지 않습니다. 모든 단일 문자가 수십 개의 다른 문자 세트에 맞는 범주를 정의해야하기 때문입니다.

const letters = ['a', 'b', 'y', 'X', 'c', 'y', 'A', 'B', 'Y']; 

function getAdditionalClass(char){
    //To do - fill arrays with the rest of the appropriate letters
    if (['y', 'g'].includes(char)) {
        return "tail"; 
    }
    if (['b', 'd'].includes(char)) {
        return "stalk"; 
    }
    
    if (['a', 'c'].includes(char)) {
        return "small"; 
    }
    
    return "capital"; 
}

letters.forEach(v => {
  const avatar = document.createElement("div"); 
  avatar.className = "avatar"; 
  const character = document.createElement("div");
  character.textContent = v; 
  character.className = `character ${getAdditionalClass(v)}`; 
  
  avatar.appendChild(character); 
  
  const root = document.getElementById("root"); 
  
  root.appendChild(avatar); 
  
});
.avatar {
    border-radius: 50%;
    display: block;
    text-align: center;
    width: 125px;
    height: 125px;
    font-size: 60px;
    background-color: rgb(81, 75, 93);
    font-family: "Segoe UI";
    margin-bottom: 10px;
}

.character {
    position: relative;
    transform: translateY(-50%);
    line-height: 100%;
    color: #fff;
}


.small {
    top: 45%; 
}

.stalk {
    top: 50%;
}

.tail {
    top: 41%;
}

.capital {
    top: 50%;
}

#root {
    display: flex; 
    flex-flow: row wrap; 
}
<div id = "root">

</div>


나는 이런 것을 피하기를 바랐지만 유일한 해결책 일 수 있습니다. 다른 것이 없다면, 아마도 이것을 사용할 것입니다. 감사합니다
Chron Bag

2
문자가 임의의 유니 코드 문자 (알파벳) 일 수 있으면이 문자는 작동하지 않습니다.
화려한

당신은 ÂËâë
Temani Afif

아 그렇습니다, 좋은 지적 @Brilliand 내 사용자는 표시 이름으로 유니 코드 텍스트를 사용할 수 있으므로이 솔루션은 훨씬 더 취약합니다.
Chron Bag

0

까다로운 상황입니다!

내가 말할 수있는 건,이는 기본적으로 확장 가능한 (즉, 할 가장 어려운 것 %, vw또는 vh대신 값 px또는 em). 모바일이나 태블릿 에서이 모양을 아름답게 보이게하려면 내 솔루션을 @media중단 점 과 함께 사용하십시오 .

내 솔루션은 기본적 으로 꼬리 가있는 소문자 요소 인지 감지 하고 꼬리 를 보완하기 위해 높이를 오프셋하는 클래스를 추가합니다.

내 테스트에서는 추가 핸들러가 필요되었다는 것을 표시하지 않은 자본 문자 또는 소문자 문자 꼬리없이 . 내가 틀렸다면 언제든지 정정하십시오.

있다 JSFiddle은 당신이 주변에 혼란과 변화 / 시험이 솔루션하십시오.

var circles = document.getElementsByClassName('circle');
var tails = ['q', 'y', 'p', 'g', 'j'] ;

Array.from(circles).forEach(render);
  
function render(element) { 		
    if(element.innerText == element.innerText.toLowerCase() &&
    	tails.includes(element.innerText)) {
    	element.className += " scale";
    }
}
.circle {
  height: 150px;
  width: 150px;
  background-color: #bbb;
  border-radius: 50%;
  display: inline-block;
  text-align: center;
  vertical-align: middle;
  line-height: 150px;
  font-size: 50px;
}

.scale {
  line-height: 135px;
}
<div>
  <div class="circle">W</div>
  <div class="circle">X</div>
</div>
<div>
  <div class="circle">y</div>
  <div class="circle">t</div>
</div>

당신의 생각과 내가 놓친 것이 있으면 알려주세요. 과거에 비슷한 문제가 있었기 때문에 이에 대한 최종 솔루션을 얻는 것이 좋습니다.


이것은 dwjohnston의 솔루션과 유사하며 그의 것과 같은 함정에 종속됩니다. 그럼에도 불구하고, 그것은 높이 평가되며 더 이상 이상적인 것이 없다면이 라인을 따라 무언가로 갈 수 있습니다.
Chron Bag

마지막 수단으로 픽셀 카운트의 경로를 내려갈 수 있다고 가정합니다. 여기서 픽셀 의 실제 높이 를 감지 하고 적절한 오프셋을 적용하는 위치 를 볼 수 있습니다 .
EGC

1
예, OP에 대한 의견에서 그 아이디어를 언급했습니다. 어쩌면 그것은 갈 길입니다.
Chron Bag

당신의 생각을 다시 한 번 알려 드리게되어 죄송합니다. 댓글이 너무 많습니다.
EGC

-1

대문자보다 소문자를 더 많이 번역 할 수 있도록 헬퍼 클래스가 필요할 것입니다. 간단한 스크립트는 이러한 도우미 클래스를 자동으로 쉽게 설정할 수 있습니다.

이것이 당신을 위해 문제를 해결하기를 바랍니다 :)

.avatar {
    border-radius: 50%;
    display: block;
    text-align: center;
    width: 125px;
    height: 125px;
    font-size: 60px;
    background-color: rgb(81, 75, 93);
    font-family: "Segoe UI";
    margin-bottom: 10px;
}

.character {
    position: relative;
    top: 50%;
    line-height: 100%;
    color: #fff;
}
.character-lowercase {
  transform: translateY(-60%);
}
.character-capital {
  transform: translateY(-50%);
}
<div class="avatar">
  <div class="character character-capital">W</div>
</div>

<div class="avatar">
  <div class="character character-lowercase">y</div>
</div>


당신의 y중심이 아닙니다. 몇 주 더!
Roko C. Buljan

나는 또한 글자가 무엇인지 미리 알지 못한다.
Chron Bag

나는 이해하지만, 문자가 대문자인지 소문자인지 확인하고 HTML을 기반으로 도우미 클래스를 배치하면 쉽게 해결할 수 있습니다.)
Ragna Roaldset

@RagnaRoaldset 나는 그가 대문자 또는 소문자를 의미하지 않는다고 생각합니다. 그는 소문자지만 다른 형태의 성격이 있음을 의미했습니다. 비교 o하고 y당신은 그것을 얻을 수 있습니다. 꼬리가있는 문자는 처음에 문제를 일으 킵니다 (소식에서 언급).
Anna

1
당신은 항상 꼬리가있는 모든 문자에 대한 배열을 만들고 클래스를 적용하기 전에 div의 문자가 일치하는지 확인하기 위해 루프를 반복 할 수 있습니다 :) 그러나 나는 그것을 얻었습니다. it :)
Ragna Roaldset
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.