1

I need all the links below to be justified vertically, i.e. on left and right side.
font-size should be as is.
Obviously the only way is to adjust letter-spacing, but is it possible to do this automatically for all links inside .wrap.

a{display:block; text-decoration:none;}
.a1{font-size:0.7rem;}
.a2{font-size:1rem;}
.a3{font-size:1rem;}
.a4{font-size:0.7rem;}
<div class='wrap'>
<a href='index.php' class='a1'>LOREM IPSUM</a>
<a href='index.php' class='a2'>DOLOR SIT</a>
<a href='index.php' class='a3'>BLUE SKY</a>
<a href='index.php' class='a4'>DEEP OCEAN</a>
</div>
Johannes
  • 64,305
  • 18
  • 73
  • 130
qadenza
  • 9,025
  • 18
  • 73
  • 126
  • Can you explain more on `left and right side.`?, is that you need in a column or row? – Manjuboyz Jun 07 '20 at 15:17
  • There is a solution for a similar question (but applying it to single words) here: https://stackoverflow.com/a/4355274/5641669 – Johannes Jun 07 '20 at 15:18
  • If your font size and style will not change, might as well find out the letter spacing that fits best and set it in your CSS. If font size or style may change, why not use JS? Fetch the largest width of all elements, then iterate through each item and maybe increment the letter spacing until desired width is reached, then move on to the next element. Seems a bit dirty but it should work. Another solution, would be to wrap each letter inside a tags in spans and use display:flex on a elements to space the letters. – Will Jun 07 '20 at 15:18
  • @Manjuboyz, in a column – qadenza Jun 07 '20 at 15:20
  • `text-align-last: justify; display: inline-block;` to wrap element? – Temani Afif Jun 07 '20 at 15:20
  • @TemaniAfif, there is a large gap between `deep` and `ocean` i.e. only word spacing is changed – qadenza Jun 07 '20 at 15:25
  • this is the meaning of *justify* – Temani Afif Jun 07 '20 at 15:26
  • I think [this is what you are looking for](https://codepen.io/Merri/pen/dquki) – MilkyTech Jun 07 '20 at 15:32
  • Source: [https://css-tricks.com/forums/topic/one-line-justified-text-design/](https://css-tricks.com/forums/topic/one-line-justified-text-design/) – MilkyTech Jun 07 '20 at 15:38
  • 1
    @ChrisL Resizing text should be done by adjusting space between characters. I think your solution adjusts the size of the text instead – Will Jun 07 '20 at 15:40
  • @Will Not my solution but I see what you mean. I didn't look at how it was being achieved, just saw the individual lines justified and so commented the example. Either way, I think it will have to be JS using a similar method. Detect the width of the string then adjust character spacing until the string width fills the container width. – MilkyTech Jun 07 '20 at 15:50

2 Answers2

3

This is what I came up with. A bit "dirty" but it does exactly what you want. You may find ways to inprove the code as mine runs the same loop twice but I wrote this quickly. At least you'll get an idea.

First, set the display of a tags to inline-block to be able to measure the largest width of all. Once you have that maxWidth, loop through all elements, wrap each character in a span, and set the display of a tags to flex.

CSS:

a{
  display: inline-block;
  width: auto;
  justify-content: space-between;
  text-decoration:none;
  clear: both;
}
a.flex{
  display: -webkit-flex;
  display: -ms-flexbox;
  display: flex;
}
.a1{font-size:0.7rem;}
.a2{font-size:1rem;}
.a3{font-size:1rem;}
.a4{font-size:0.7rem;}
a span{
  display:inline-block;
}

JS:

var elements = document.querySelectorAll(".wrap > a");
 var maxWidth = 0;
 for (var i = elements.length - 1; i >= 0; i--) {
    maxWidth = Math.max(maxWidth, elements[i].offsetWidth);
 }
 for (var i = elements.length - 1; i >= 0; i--) {
    elements[i].classList.add("flex");
    elements[i].style.width = maxWidth+ "px";
    var text = elements[i].textContent;
    text.split("");
    elements[i].innerHTML = "";
    for (var j = 0; j < text.length; j++) {
       var span = document.createElement("span");
       // Fix: issue reported by Chris L
       // Replace space with non-breaking space HTML code
       span.innerHTML = (text[j] === " ")? "&nbsp;" : text[j];
       elements[i].appendChild(span);
    }
 }

Working example here: https://jsfiddle.net/nLdx923c/

Will
  • 1,123
  • 1
  • 9
  • 22
  • 1
    This is pretty good IMO, but it sets the width of spaces between words to zero, making it look like there were no spaces at all. – Johannes Jun 07 '20 at 16:13
  • 2
    But adding a `min-width` (measured in `em`) to the spans fixes this problem: https://jsfiddle.net/0qhezcj7/ – Johannes Jun 07 '20 at 16:19
  • The inspector shows the space span as having no width, however, using "Blue Sky" as an example, when you add up the widths of each character, it is 9.78 short of the full width of 83. So the space must have that width of 9.78, although it doesn't appear that wide with the naked eye. Looking closely though, there is definitely a little space for the space span. – MilkyTech Jun 07 '20 at 19:20
  • That's true. I edited my response. Should be fine now. – Will Jun 07 '20 at 21:33
1

One way to come at least close to what you want: use text-align-last: justify, a letter-spacing value in em (i.e. relative to the font-size) and a fixed width on the wrapper element, finding appropriate values by trial & error:

.wrap {
  width: 95px;
}

a {
  display: block;
  text-decoration: none;
}

.a1 {
  font-size: 0.7rem;
}

.a2 {
  font-size: 1rem;
}

.a3 {
  font-size: 1rem;
}

.a4 {
  font-size: 0.7rem;
}

a {
  text-align-last: justify;
  letter-spacing: 0.08em;
}
<div class='wrap'>
  <a href='index.php' class='a1'>LOREM IPSUM</a>
  <a href='index.php' class='a2'>DOLOR SIT</a>
  <a href='index.php' class='a3'>BLUE SKY</a>
  <a href='index.php' class='a4'>DEEP OCEAN</a>
</div>
Johannes
  • 64,305
  • 18
  • 73
  • 130
  • large gap between `deep` and `ocean` in any case, but... I see - this is the max possible with css – qadenza Jun 07 '20 at 16:42