Remove space below the text baseline with CSS - html

Lately I've been working with Japanese text, and I've found a rather annoying property. In Japanese, unlike English, glyphs do not extend below the text baseline. This example should show what I mean:
div {
font-size: 72pt;
display: inline-block;
text-decoration: underline;
border: 1px solid red;
margin: 10px;
text-align: center;
}
<div lang="ja">日本語</div>
<div lang="en">English</div>
Notice how the "g" in "English" extends below the underline, but none of the characters in 日本語 do. This is typical of Japanese text. Despite this, space is still reserved below the underline, and in fact on my screen the Japanese text reserves more space than the English text does. My question is this:
Is there a way to remove this space with CSS which is reliable across changing fonts and font sizes? I can see at least two possible approaches:
Remove the space below the baseline directly.
Move the baseline to be at the bottom of the containing box.

You need to reset the line-height so it's not bigger than 1. The initial value is normal which depends on the User Agent of the browser, on the font-family and on the font-size, but it's some number between 1 and 1.2 in general. Here's more information if you're interested.
div {
font-size: 72pt;
display: inline-block;
text-decoration: underline;
border: 1px solid red;
margin: 10px;
text-align: center;
line-height: 1;
}
<div lang="ja">日本語</div>
<div lang="en">English</div>

Just set the line height to the same size as the font size: line-height: 72pt. This normalizes the space that's taken for the font height. Of course you can take every value for the line height that you like, to adjust that space. More information to line-height at MDN.
div {
font-size: 72pt;
line-height: 72pt;
display: inline-block;
text-decoration: underline;
border: 1px solid red;
margin: 10px;
text-align: center;
}
<div lang="ja">日本語</div>
<div lang="en">English</div>

Related

Align h1 text with surrounding borders (supported by gmail)

I'm trying to get lines to surround an h1 but I'm having problems aligning the text with the surrounding lines. I've used embedded before / after attributes but I couldn't get them to work in Gmail so I opted of an inline attribute using borders on the h1. Currently the text "January 2018" is aligning below the surrounding lines. See code below.
h1 {
text-align: center;
color: #ffe800;
font-family: proxima-nova, sans-serif;
font-size: 22px;
font-weight: bold;
text-transform: uppercase;
}
<h1 style="border-left: 150px solid #ffffff; border-right: 150px solid #ffffff; height: 3px; display: block;">January 2018</h1>
Thanks!
I think you need to change your display property from display:block to display:inline

Vertically align characters inside input

How do I vertically align the characters/text inside an input without changing the height of the input (it has to be exactly 28px)? The input has this CSS, so I don't understand why it has some padding-top (?):
input {
font-family: arial;
font-size: 28px;
line-height: 28px;
height: 28px;
padding: 0;
border: none;
outline: none;
background-color:#cdcdcd;
}
<input value="asdg">
Some letters like g, p and q get cut off
Removing the margin-bottom doesn't help.
https://jsfiddle.net/4rtL6415/
There is no padding top, it's about font size. I've changed your snippet input with a special char that fit the whole height (I'll explain below):
input {
font-family: arial;
font-size: 28px;
line-height: 28px;
height: 28px;
padding: 0;
border: none;
outline: none;
background-color:#cdcdcd;
}
<input value="ᅡgs">
This image:
Explain how a font is construct. 99% of the time you'll see characters with Body < EM and that's why we may think that there is a sort of padding-top.
Sometimes, you'll cross characters for which Body == EM, that's the case of ᅡ (and a lot of others).
What you are seeing is not a bug but a feature. From here you have 3 choices:
Changing the font-size;
Changing the input height;
Changing the font-family for one that doesn't "overflow".
The choice is all yours.
The Problem
In some fonts, characters with descenders, like g, p, q, and y, "overflow" the vertical space defined by the font-size property. Normally, that's not a problem, because the line-height property provides enough extra space to accommodate the descenders. However, if the characters are placed in a container element with a fixed height that's less than the line-height, the descenders may get clipped if that's how the container handles overflow (text inputs being one example of such).
If you were hoping to bump the text up a few notches to avoid the clipping, then you'll be disappointed to know that there is currently no way to reposition text within its own line-height. (vertical-align, in case you were wondering, positions an inline element relative to its parent.) However, there are a few CSS tricks that we can use to achieve the same visual effect...
Solution 1 (Webkit only)
This one works by giving the input a large enough height to fit the font's lower extremities, and then using clip-path to trim it back down to 28px. This is probably the most elegant solution, but unfortunately, clip-path isn't well supported outside of Webkit browsers (Chrome, Safari, Opera).
input {
display: inline-block;
padding: 0;
border: none;
height: 32px;
font-size: 28px;
line-height: 32px;
font-family: arial;
background: #cdcdcd;
vertical-align: baseline;
-webkit-clip-path: inset(4px 0px 0px 0px);
clip-path: inset(4px 0px 0px 0px);
}
input: <input value="asdg">
Solution 2
This one was inspired by DebRaj's answer, but mine uses an inline-block wrapper instead of a block (not sure how you would use it otherwise). Like the previous solution, it increases the height of the input, but instead of using clip-path to trim it back down, it uses a container element with overflow: hidden;. This is probably the most practical approach until support for clip-path improves.
.text {
display: inline-block;
vertical-align: baseline;
overflow: hidden;
margin: 7px 0 -7px 0;
height: 28px;
}
.text > input {
margin-top: -4px;
border: none;
padding: 0;
background: #cdcdcd;
font-size: 28px;
line-height: 32px;
font-family: arial;
}
input:<span class="text"><input value="asdg"></span>
Solution 3
Although you can't reposition text within its own line-height, this may be the next best thing. If you set the line-height to something less than the font-size, the text will indeed move upward relative to its normal baseline. That means you can bring the clipped parts into view without changing the container height. Unfortunately, if you try this with a text input, you'll discover a strange quirk: line-height is completely ignored if it's less than the input's height. So we'll have to substitute a different element, and turn it into an editable textbox somehow. That can be accomplished with the contenteditable attribute.
.fauxTextInput {
display: inline-block;
vertical-align: baseline;
margin: 6px 0 -6px 0;
padding: 0 3px 0 3px;
width: 9em;
height: 28px;
overflow: hidden;
font-size: 28px;
line-height: 23px;
font-family: arial;
background: #cdcdcd;
}
Faux input: <span class="fauxTextInput" contenteditable>asdg</span>
As #Thomas mentioned there is a default spacing as per font construction rules. If we concentrate the output you want to achieve is make font exact same height at the input area, you can wrap your input into a div and give that a height to adjust the input into it using as a mask.
Here is the code:
<div class="input-wrapper">
<input value="asdg">
</div>
CSS:
.input-wrapper{
position: relative;
font-family: arial;
width: 100%;
height: 90%;
padding: 0;
background-color: #fff;
overflow: hidden;
}
.input-wrapper input {
display: block;
width: 100%;
height: 124%;
margin-top: -0.19em;
margin-bottom: 0em;
font-size: 28px;
padding: 0;
outline-offset: 0;
border: none;
}
.input-wrapper input:focus{
outline-offset: 0;
outline: 0;
border: none;
box-shadow: none;
}
fiddle: https://jsfiddle.net/x8jmLp8m/12/
Hope that helps.
Although there have been plenty of answers. I thought I'd add my solution to the bunch.
In this Fiddle, you can see how I managed to create an input field with a span tag, and the contenteditable attribute. The pros of taking this route are that the input field can stretch and wrap and that we can make it exactly 28px high.
In the CSS, I've added the following rules that are important:
span{
display: inline-block;
font-size: 25px; /*higher than 25px simply doesn't fit a 28px container*/
line-height: 1;
padding: calc(-.5em + 14px) 0;
}
display, of course, to style the bunch
font-size to declare the height of the font
line-height of 1 to make sure the text actually takes up 25px by default.
a padding of calc(-.5em + 14px) 0. And that's the tricky part
Because of this padding, the element will stay 28px high, while still centering the text. See the table below to see how the calculation works. The font-size and output * 2 always add up to a minimum of 28.
font-size | calculation | output |
--------------------------------------
50px | calc( -25px + 14px) | -11px | a negative padding translates to a padding of 0
25px | calc(-12.5px + 14px) | 1.5px |
20px | calc( -10px + 14px) | 4px |
15px | calc( -7.5px + 14px) | 6.5px |
10px | calc( -5px + 14px) | 9px |
With this code, you can edit the span's height by editing the 14px part in the calc, and edit the font-size without having to recalculate yourself
Hope this helps
Edited your fiddle here
The problem is your font is larger than the height of the element enclosing it. So you just need to set both the height and line-height to a couple of px larger than the font size you're using.
Hope this helps.
Just decrease the font-size:
input {
font-family: arial;
font-size: 20px;
line-height: 28px;
height: 28px;
padding: 0;
border: none;
outline: none;
background-color:#cdcdcd;
}
<input value="asdg">
I hope this will help you know what you want to achieve
In CSS, the line-height
property sets the height of
an entire line of text, so the
difference between the font-
size and the line-height is
equivalent to the leading (as
shown in the diagram above).
And our css is this
input {
font-family: arial;
font-size: 28px;
line-height: 28px;
height: 28px;
padding: 0;
border: none;
outline: none;
background-color:#cdcdcd;
}
Here we have set line-height and font size equal and because of that decent is getting cut.So you either need to decrease font-size or increase line-height.
input {
height:34px;
}
Just change height and line-height to 40px or more.
https://jsfiddle.net/525raf3L/
input {
font-family: arial;
font-size: 28px;
line-height: 40px;
height: 40px;
padding: 0 12px;
border: none;
outline: none;
background: yellow;
}
<input value="asdg">

Why is my textarea higher up than its neighbor?

Picture:
.left {
border: 1px solid red;
}
textarea {
border: 1px solid blue;
}
.parent {
border: 1px solid green;
}
<div class='parent'>
<span class='left'>
<span>one</span>
<span>two</span>
</span>
<textarea></textarea>
</div>
Codepen
Why is my textarea higher up than its neighbor?
It's not.
Let me explain.
First, a bit of background:
Your span and textarea elements are (by default) inline elements.
Browsers normally provide a little bit of whitespace underneath inline elements for descenders.
To understand descenders...
Look at this line of text. Notice there are no letters that breach the baseline.
Now look at the following sentence:
By just crossing the bridge he probably got away.
Note the letters "y", "j", "p" and "g". These letters breach the baseline and are known in typography as "descenders".
[
Source: Wikipedia.org
The gap you're seeing is not margin or padding, but simply the browser providing room to accommodate these lowercase letters. In short, this is called baseline alignment.
baseline
The line upon which most letters "sit" and below which descenders extend.
[
Source: Wikipedia.org
So why, somebody might ask, does the browser provide this space for textarea, img, input and other inline elements, that don't need space for descenders?
Because the browser adjusts for the possibility that you may have text before or after one of those elements on the same line.
Now, to your image and code...
On first glance it clearly appears that the textarea is higher up than the span element. But if you take a closer look...
...you'll see they are perfectly aligned. Both span and textarea are providing space for descenders.
The borders you've added contribute to the appearance of misalignment because the textarea border wraps a clearly delineated box while excluding descender space, but the span border wraps the text and the descender space. If you remove the red border the misalignment is less pronounced.
In terms of a solution, here are two options:
Add vertical-align: bottom to the textarea rule, OR
Add display: block to the textarea rule.
Adam,
If you add the following to your existing css, you should get your desired results.
.left{
display:inline-block;
vertical-align: text-bottom;
}
textarea{
margin:0px;
vertical-align: text-bottom;
}
You can see a working example at the following url: https://jsfiddle.net/YOOOEE/z8pwpms6/
If you have two span elements, the high will be the same. Spans have display:inline; by default.
<span class="left">
<span>one</span>
<span>two</span>
</span>
<span class="right">
<span>one</span>
<span>two</span>
</span>
All browsers have defaults styles for textareas:
textarea {
-webkit-appearance: textarea;
background-color: white;
border: 1px solid;
border-image-source: initial;
border-image-slice: initial;
border-image-width: initial;
border-image-outset: initial;
border-image-repeat: initial;
-webkit-rtl-ordering: logical;
-webkit-user-select: text;
flex-direction: column;
resize: auto;
cursor: auto;
padding: 2px;
white-space: pre-wrap;
word-wrap: break-word;
}
input, textarea, keygen, select, button {
margin: 0em;
font: 13.3333px Arial;
text-rendering: auto;
color: initial;
letter-spacing: normal;
word-spacing: normal;
text-transform: none;
text-indent: 0px;
text-shadow: none;
display: inline-block;
text-align: start;
}
My solution:
.parent {
border: 1px solid green;
display: flex;
}

h1 element distance to border differs at top and bottom

CSS:
h1 {
width: 25%;
margin: 11rem auto;
font-family: 'Baron Neue';
font-size: 4vw;
color: white;
text-align: center;
border-top: solid 2px white;
border-bottom: solid 2px white;
}
HTML:
<h1>POTJESMARKT</h1>
The h1 tag has <body> </body> as it's parent.
The problem is that the border on the top isn't attached to h1, while there's no padding there. What I would like eventually is about a 1rem padding between h1 and the border, at the top and bottom. I could solve this by adding padding at the bottom of h1, but if I then resize my browser window, the distance from h1 to border isn't equal anymore on top and bottom.
Solved it in an 'ugly' way:
I added padding-bottom: 1vw;
This way, the padding scales together with h1, which makes it acceptable.
Seeing as (technically), it's working here:
html,body{background:red;}
h1 {
width: 25%;
margin: 11rem auto;
font-family: 'Baron Neue';
font-size: 4vw;
color: white;
text-align: center;
border-top: solid 2px white;
border-bottom: solid 2px white;
}
<h1>POTJESMARKT</h1>
In which since I haven't actually got your font style installed, I believe your problem is with the font itself. In order to 'fix' this you could;
A: Find out the font's baseline margin (in px) and add the extra 'top' padding to your h1 element
B: Use a different/more common font
C: 'Guess' by adding some padding-bottom to your element.
Just some points I would like to note:
Ensure you import your font (so that everyone can 'use' it (i.e. google fonts))
I wouldn't really be that keen on using vw and vh unless actually needed
Again, personal preference would stop me from using 'rem' values, and either stick to em, px, or otherwise.
Here is a semantic answer:Header fiddle
html:
<h1><strong>Potjes market</strong><h1>
css:
h1 {
font-size:4em;
border:3px solid blacK;
}
h1 > strong {
position:relative;
bottom:0.1em;
}`
This pushes the text slightly up so that the border looks even above and below

How do you create consistant vertical spacing while using different line-heights?

I am using different line-heights in my css and it is causing issues with my vertical spacing. I would like there to be the same amount above the horizontal rule as there is below.
This is an example of my issue:
My HTML
<div class="intro">
<p>The powered flight took a total of about eight and a half minutes. It seemed to me it had gone by in a lash. We had gone from sitting still on the launch pad at the Kennedy Space Center to traveling at 17,500 miles an hour in that eight and a half minutes. It is still mind-boggling to me. </p>
</div>
<hr />
<div class="normal">
<p>I recall making some statement on the air-to-ground radio for the benefit of my fellow astronauts, who had also been in the program a long time, that it was well worth the wait.</p>
</div>
<hr />
<div class="normal">
<p>The powered flight took a total of about eight and a half minutes. It seemed to me it had gone by in a lash. We had gone from sitting still on the launch pad at the Kennedy Space Center to traveling at 17,500 miles an hour in that eight and a half minutes. It is still mind-boggling to me.</p>
</div>
My CSS
.intro p { margin-bottom: 24px; font-size: 24px; line-height:36px; }
.normal p { margin-bottom: 18px; font-size: 16px; line-height:18px; }
hr { border-top: 1px solid rgb(200,200,200); margin: 10px 0}
You can also see it here:
http://codepen.io/dachan/pen/Csueb
Are there any solutions to my problem, minus having to manually create different margins for the hr tag?
Also, I do intend on having multiple paragraphs so any solution omitting a margin-bottom would not work for me.
If you know where you are in the text flow, just use a different rule style between the intro and the first text unit. The following will give you the same spacing above and below the first <hr/>
hr { border-top: 1px solid rgb(200,200,200); margin: 10px 0 28px 0 }
I do not use the <hr> tag cause it is hard o style properly, defintly in the great browser called IE.
In stead I use an empty div with a class .hr applied to it. My css would look something like this:
.hr {
border-top: 1px solid black;
margin-top: 10px;
height: 10px;
}
If you set the line-height of the text elements equal to the font-size, therefore making the height of the element equal to the height of the text. when you add the hr element the spacing should be the same.
.intro p { font-size: 24px; line-height:24px; }
.normal p { font-size: 16px; line-height:16px; }
hr { border-top: 1px solid rgb(200,200,200); margin: 10px 0}
I don't think your issue here is your line-height. You have defined a bottom margin for each of your paragraphs, but no top margin. Because of this, your second paragraph has default margin above it, making it closer to the hr.
One possible solution is to simply add margin-top equal to your margin-bottom.
.intro p { margin-bottom: 24px; font-size: 24px; line-height:36px; }
.normal p { margin-top: 18px; margin-bottom: 18px; font-size: 16px; line-height:18px; }
hr { border-top: 1px solid rgb(200,200,200); margin: 10px 0; }
Example here: http://jsfiddle.net/3BEkL/1/
The other possibility, which may not be what you want, since it seems you are going for different spacing between the hr's based on the font-size/line-height of each paragraph, is
remove all margin styling from the paragraph elements and only apply margins to the hr elements.
.intro p { font-size: 24px; line-height:36px; }
.normal p { font-size: 16px; line-height:18px; }
hr { border-top: 1px solid rgb(200,200,200); margin: 30px 0; }
Example here: http://jsfiddle.net/3BEkL/2/