3

I would like to have a spacing between a h1 and a span, which should be 30px. It should be 30px from the bottom of the letters from the h1 to the top of the letters of the span, which comes below the h1, here a picture where the spacing of 30px should be (blue box shows spacing):

enter image description here

My h1 and span have some line-height. I made a border around it, so the line-height is visible. If I set now a margin-bottom of 30px to the h1 it looks like this:

enter image description here

The spacing begins at the end of the h1 element and ends at the start of the span element. The line-height is between the start/end of the element and the letters. So the spacing includes also the line-height and it is not exactly 30px. What's the best way to solve this? I know, that I could set the margin-bottom like this: margin-bottom: 30px - [LINE-HEIGHT]; But how can I know, how much the two red boxes (line-heights) are, to subtract it correctly so that the spacing becomes exactly 30px?

h1 {
  font-family: Arial;
  font-size: 45px;
  line-height: 54px;
  letter-spacing: 0;
  color: darkred;
  border: 1px solid black;
  margin: 0 0 30px;
}

span {
  font-family: Arial;
  font-size: 30px;
  line-height: 39px;
  letter-spacing: 0;
  color: gray;
  border: 1px solid black;
}
<h1>Default main title</h1>
<span>Proin eget tortor risus. Vivamus magna justo, lacinia</span>

Here is my codepen example: https://codepen.io/STWebtastic/pen/QarjJO

I hope this is clear enough.

David Thomas
  • 249,100
  • 51
  • 377
  • 410
webta.st.ic
  • 4,781
  • 6
  • 48
  • 98
  • @DavidThomas Thanks for your input, is it bether now? Cheers – webta.st.ic Jan 11 '18 at 13:00
  • Much appreciated! – David Thomas Jan 11 '18 at 13:05
  • @DavidThomas O yeah sure, sorry. In the past I used to work only with the stackoverflow snippet, which generates the code automaticly in the question. Recently I started with codepen and forget out of habit that then the code in the question is missing. Now it should be good. – webta.st.ic Jan 11 '18 at 13:05
  • 1
    @MrBuggy the space below the h1 is for letters like g and y - what happens when one of them is added? Your space will no longer be 30px; – Pete Jan 11 '18 at 13:48
  • @Pete Yes I know. But if I could get the height of this spaces and subtract it from my margin-bottom it would work, like I wrote. So for example if the space within the h1 is 10px and the other one within the span 5px this would be 15px + my margin-bottom of 30px = 45px and not 30px. So if I could find out the spaces and subtract it from my margin like this: margin-bottom: 30px - calc(10px + 5px); I would get a margin-bottom of 15px which would "generate" the space of 30px with the spaces. But I don't know how to get the space height to subtract it, this would be my solution. – webta.st.ic Jan 11 '18 at 15:20
  • perhaps you need to find out what the font aspect ratio (ie percentage taken for ascender, percentage taken for descender, etc) for Arial is and then work on a solution based on that – Pete Jan 11 '18 at 15:25
  • Or do something like this to figure out the descender and ascender heights: https://stackoverflow.com/questions/10180148/how-to-calculate-descender-height-in-javascript – Pete Jan 11 '18 at 15:46

4 Answers4

2

hmmm not really how internet typography works.

Setting line-height:100%; margin:0; padding:0; and box-sizing:border-box; (so the borders are not added to the height) will get you somewhat closer.

But the real problem is that in browsers, line-heights include the spacing reserved for descenders (think the bottom parts of q, j, g)and ascenders. Plus some extra bits that I cannot really explain. I'm no designer, even less of a font expert.

So the only way you can actually achieve what you'r looking for is by adjusting the line-height with magic numbers (those that you get from trial and error) to a lower value than your actual font-size. The right value is normally in the ballpark of 68-70%, but there's no formula valid for any font size, let alone any font.

body {
  font-family: Arial;
}
*{
box-sizing:border-box;
}


h1 {
  font-size: 45px;
  line-height:31px;
  letter-spacing: 0;
  color: darkred;
  border: 1px solid black;
  margin: 0 0 30px;
}

p {
  font-size: 30px;
  line-height:21px;
  color: gray;
}


h1, p{
  padding:0;
  margin:30px 0;
  border: 1px solid black;
}
<h1>Default qgj main Title</h1>

<p>Proin eget tortor risus. Vivamus magna justo, </p>

this is, of course, extremely fragile and prone to issues. So your best bet to achieve something somewhat similar is to keep using magic numbers in the margins instead.

There are some formulas out there to make your guesses easier, but they are really dependant on your selected font, font size, etc.So again, magic numbers.

Facundo Corradini
  • 3,825
  • 9
  • 24
  • In a more simplified situation, the OP could get closer than "_somewhat similar_". There is the unit `ex`, which means the height of lowercase letters. So... if all letters are exactly that height, and the font sizes don't vary, then you can have exactly 30px of room between the rows, by setting the height to `1ex + 30px`. https://jsfiddle.net/kj01qgmr/ (Of course this doesn't work if you have uppercase letters too, if if the elements have different font sizes.) – Mr Lister Jan 11 '18 at 13:56
  • @MrLister awesome contribution! probably not what he really needs as his snippet had uppercase letter already, but I totally forgot the existence of ex units at all – Facundo Corradini Jan 11 '18 at 14:07
0

I think you should read this first: https://iamvdo.me/en/blog/css-font-metrics-line-height-and-vertical-align

As you can see, a font itself has a certain line height (the white space between the character and the bottom border). So if you set the font-size: 45px and line-height:45px there will still be a white space (try it in your fiddle and inspect the element for proof). It has to do how the font was rendered by the em-square, which is not proportional.

You can choose a font that has characters which use the entire em-square. But I don't know how easy is to find this...

As far as I can tell, the best you can do is indeed what already was suggested: trial and error until you figure 30px.

0

Some characters such as the lowercase j or g have a "descender". Thus your question is flawed to begin with because you don't seem to account for those descenders which are part of font height.

WebDevBooster
  • 14,674
  • 9
  • 66
  • 70
0

To simplify the question, you’re asking: How do I ensure that there is a 30px space between the baseline of an h1 element and the cap line of a span below it?

It looks like there is a nifty project on GitHub called cap-height that can help you with this as long as you’re loading your typefaces using Web Font Loader.

You can calculate the cap height of both your h1 and your span, set their respective line-height to match their cap heights, and then add padding-bottom: 30px to your h1. You’ll also want to set margin: 0 so that you’re eliminating any vertical space between the two elements.

Here’s a fiddle example of this that I did manually.