Force Non-Monospace Font into Fixed Width Using CSS - css

Is there any way to force a font to be monospaced using CSS?
By this I mean, using a non-monospace font, can you force the browser to render each character at a fixed width?

If this is for aligning digits in tables where some fonts (with traditional typography) render them by default with variable width (e.g. Segoe UI on Windows), you should look into CSS properties for:
font-variant-numeric: tabular-nums;
(this disables the proportional-nums default value for the numeric-spacing variant supported at least by OpenType fonts, and possibly by other font formats supported by the text renderer of your web browser for your particular platform)
No JavaScript needed! It is the cleanest way to disable the variable-width glyphs in these fonts and force them to use tabular digits (this generally uses in the same glyphs in the same font, but their leading and trailing gap is increased so the 10 digits from 0 to 9 will render at the same width; however some font may avoid the visual variable interdigit spacing and will slightly widden some digits, or could add bottom serifs to the foot of digit 1.
Note that this does not disable the variable height observed with Segoe UI (such as some digits will be x-height only like lowercase letters, others will have ascenders or descenders). These traditional digit forms may be disabled with CSS too, using
font-variant-numeric: lining-nums;
(this disables the default oldstyle-nums value for the numeric-figure variant supported at least by OpenType fonts, and by possibly other font formats supported by the text renderer of your web browser for your particular platform)
You can combine both:
font-variant-numeric: tabular-nums lining-nums;
--
The snippet below demonstrates this using a single proportional font (not monospaced!) featuring shape variants for digits, such as 'Segoe UI' on Windows and shows the different horizontal and vertical alignments produced.
Note that this style does not prohibit digits to change width if different styles like bold or italic is applied instead of medium roman as shown below because these will use different fonts with their own distinct metrics (this is not warrantied as well with all monospace fonts).
html { font-family: 'Segoe UI'; /* proportional with digit variants */ }
table { margin: 0; padding: 0; border: 1px solid #AAA; border-collapse: collapse; }
th, td { vertical-align:top; text-align:right; }
.unset { font-variant-numeric: unset; }
.traditional { font-variant-numeric: proportional-nums oldstyle-nums; }
.lining { font-variant-numeric: proportional-nums lining-nums; }
.tabular-old { font-variant-numeric: tabular-nums oldstyle-nums; }
.tabular-new { font-variant-numeric: tabular-nums lining-nums; }
.normal { font-variant-numeric: normal; }
<table>
<tr><th>unset<td><table width="100%" class="unset">
<tr><td>Rs12,34,56,789.00/Gal<td><i>Difference Rs86,41,97,532.11/Gal
<tr><td>Rs98,76,54,321.11/Gal<td><b>Total Rs1,11,11,11,110.11/Gal
</table>
<tr><th>traditional<td><table width="100%" class="traditional">
<tr><td>Rs12,34,56,789.00/Gal<td><i>Difference Rs86,41,97,532.11/Gal
<tr><td>Rs98,76,54,321.11/Gal<td><b>Total Rs1,11,11,11,110.11/Gal
</table>
<tr><th>lining<td><table width="100%" class="lining">
<tr><td>Rs12,34,56,789.00/Gal<td><i>Difference Rs86,41,97,532.11/Gal
<tr><td>Rs98,76,54,321.11/Gal<td><b>Total Rs1,11,11,11,110.11/Gal
</table>
<tr><th>tabular-old<td><table width="100%" class="tabular-old">
<tr><td>Rs12,34,56,789.00/Gal<td><i>Difference Rs86,41,97,532.11/Gal
<tr><td>Rs98,76,54,321.11/Gal<td><b>Total Rs1,11,11,11,110.11/Gal
</table>
<tr><th>tabular-new<td><table width="100%" class="tabular-new">
<tr><td>Rs12,34,56,789.00/Gal<td><i>Difference Rs86,41,97,532.11/Gal
<tr><td>Rs98,76,54,321.11/Gal<td><b>Total Rs1,11,11,11,110.11/Gal
</table>
<tr><th>normal<td><table width="100%" class="normal">
<tr><td>Rs12,34,56,789.00/Gal<td><i>Difference Rs86,41,97,532.11/Gal
<tr><td>Rs98,76,54,321.11/Gal<td><b>Total Rs1,11,11,11,110.11/Gal
</table>
</table>
Reference: https://developer.mozilla.org/docs/Web/CSS/font-variant-numeric

Why not think outside the box and inside a table for this:
<table cellpadding="0" cellspacing="0">
<tr><td>T</td><td>h</td><td>e</td><td></td><td>r</td><td>a</td><td>i</td><td>n</td><td></td><td>i</td><td>n</td><td></td><td>S</td><td>p</td><td>a</td><td>i</td><td>n</td><td></td><td>s</td><td>t</td><td>a</td><td>y</td><td>s</td></tr>
<tr><td>m</td><td>a</td><td>i</td><td>n</td><td>l</td><td>y</td><td></td><td>i</td><td>n</td><td></td><td>t</td><td>h</td><td>e</td><td></td><td>p</td><td>l</td><td>a</td><td>i</td><td>n</td><td>s</td><td>.</td></tr>
</table>

You can't do this with CSS. Even if you could, the result will look horrible:
If you really do need to do this, you could use JavaScript to wrap each individual character in an element (or just do it by hand):
function wrap_letters($element) {
for (var i = 0; i < $element.childNodes.length; i++) {
var $child = $element.childNodes[i];
if ($child.nodeType === Node.TEXT_NODE) {
var $wrapper = document.createDocumentFragment();
for (var i = 0; i < $child.nodeValue.length; i++) {
var $char = document.createElement('span');
$char.className = 'char';
$char.textContent = $child.nodeValue.charAt(i);
$wrapper.appendChild($char);
}
$element.replaceChild($wrapper, $child);
} else if ($child.nodeType === Node.ELEMENT_NODE) {
wrap_letters($child);
}
}
}
wrap_letters(document.querySelectorAll('.boxes')[0]);
wrap_letters(document.querySelectorAll('.boxes')[1]);
.char {
outline: 1px solid rgba(255, 0, 0, 0.5);
}
.monospace .char {
display: inline-block;
width: 15px;
text-align: center;
}
<h2 class="boxes">This is a title</h2>
<h2 class="boxes monospace">This is a title</h2>

I've just found the text-transform: full-width; experimental keyword, which:
[...] forces the writing of a character [...] inside a square [...]
text-transform | MDN
Combined with negative letter-spacing, you can get not-so-horrible results:
<style>
pre {
font-family: sans-serif;
text-transform: full-width;
letter-spacing: -.2em;
}
</style>
<!-- Fixed-width sans-serif -->
<pre>
. i I 1 | This is gonna be awesome.
ASDFGHJK | This is gonna be awesome.
</pre>
<!-- Default font -->
. i I 1 | This is gonna be awesome.
<br>
ASDFGHJK | This is gonna be awesome.

Well, you didn't say using only CSS. It is possible to do this with just a little bit of Javascript to wrap each letter in a span. The rest is in CSS...
window.onload = function() {
const secondP = document.getElementById('fixed');
const text = secondP.innerText;
const newText = text.split('').map(c => {
const span = `<span>${c}</span>`;
return span;
}).join('');
secondP.innerHTML = newText;
}
p {
position: relative;
border: 1px solid black;
border-radius: 1em;
padding: 1em;
margin: 3em 1em;
}
p::after {
content: attr(name);
display: block;
background-color: white;
color: green;
padding: 0 0.5em;
position: absolute;
top: -0.6em;
left: 0.5em;
}
#fixed span {
display: inline-block;
width: 1em;
text-align: center;
}
<p id="variable" name="Variable Width">It might not look nice, but with a little Javascript, I can force a variable width font to act like a fixed-width font.</p>
<p id="fixed" name="Fixed Width">It might not look nice, but with a little Javascript, I can force a variable width font to act like a fixed-width font.</p>
In a paragraph with regular text, it looks terrible, but There are instances when this makes sense. Icon fonts and Unicode symbols could both make use of this technique.
I found this question while trying to find a solution for Unicode symbols that were shifting regular text to the right when they were replaced with other Unicode symbols.

I've done a verry pretty thing sometimes for countdowns:
HTML:
<div class="counter">
<span class="counter-digit counter-digit-0">2</span>
<span class="counter-digit counter-digit-1">4</span>
<span class="counter-digit counter-digit-divider">/</span>
<span class="counter-digit counter-digit-2">5</span>
<span class="counter-digit counter-digit-3">7</span>
</div>
SCSS:
$digit-width: 18px;
.counter {
text-align: center;
font-size: $digit-width;
position: relative;
width : $digit-width * 4.5;
margin: 0 auto;
height: 48px;
}
.counter-digit {
position: absolute;
top: 0;
width: $digit-width;
height: 48px;
line-height: 48px;
padding: 0 1px;
&:nth-child(1) { left: 0; text-align: right; }
&:nth-child(2) { left: $digit-width * 1; text-align: left;}
&:nth-child(3) { left: $digit-width * 2; text-align: center; width: $digit-width / 2} // the divider (/)
&:nth-child(4) { left: $digit-width * 2.5; text-align: right;}
&:nth-child(5) { left: $digit-width * 3.5; text-align: left;}
}

You can wrap the seconds digits in a span and style it like...
.time-seconds {display: inline-block;width: .52em;text-align: center;}
See Snippet.
function padlength(what) {
var output = (what.toString().length == 1) ? "0" + what : what;
return output;
}
function displaytime() {
var serverdate = new Date();
var dd = "am";
var hh = serverdate.getHours();
var h = hh;
if (h >= 12) {
h = hh - 12;
dd = "pm";
}
if (h == 0) {
h = 12;
}
h = parseInt(h);
var sec = String(padlength(serverdate.getSeconds()));
var timeFixed = h + ':' + padlength(serverdate.getMinutes()) + ':<span class="time-seconds">' + sec.charAt(0) + '</span><span class="time-seconds">' + sec.charAt(1) + '</span> ' + dd;
timeVariable = h + ':' + padlength(serverdate.getMinutes()) + ':' + sec + ' ' + dd;
document.getElementById("servertime-fixed").innerHTML = timeFixed;
document.getElementById("servertime-variable").innerHTML = timeVariable;
}
window.onload = function() {
displaytime();
setInterval("displaytime()", 1000);
};
center {
font-size: 3em;
font-family: Cursive;
}
.time-seconds {
display: inline-block;
width: .52em;
text-align: center;
}
<html>
<body>
<center id="servertime-fixed">H:MM:SS mm</center>
<center id="servertime-variable">H:MM:<span class="time-seconds">S</span><span class="time-seconds">S</span> mm</center>
</body>
</html>

i just had the same problem. my font didn't support font-variant-numeric: tabular-nums (which i knew about) and the other solutions didn't suit me, so i came up with this one - in my case i just had to expand letter spacing and then squash the (gigantic) zeros to make it look acceptable:
CSS:
.squashzeros { letter-spacing:.2em; }
.squashzeros span { display:inline-block; margin:0 -.09em; }
JS:
document.querySelectorAll('.squashzeros').forEach((o)=>{
o.innerHTML = o.innerText.replaceAll(/0/g,'<span>0</span>');
});
unfortunately i found no css-only solution.

No, not unless it's an actual mono-spaced font.

A mix of answers from Márton Tamás and nïkö:
document.querySelectorAll('pre').forEach( o => {
o.innerHTML = o.innerText.replace(/(.)/g, '<i>$1</i>');
});
pre i {
font-style: normal;
font-family: serif;
display: inline-block;
width: 0.65em;
text-align: center;
}
<!-- Fixed-width serif -->
<pre>
. i I 1 | This is gonna be awesome. 12:10
ASDFGHJK | This is gonna be awesome. 08:51
</pre>
<!-- Default font -->
. i I 1 | This is gonna be awesome. 12:10
<br>
ASDFGHJK | This is gonna be awesome. 08:51

No, there is no way to force anything in CSS. And there isn’t even a way to suggest that a non-monospace font be rendered as a monospace font.

Related

Apply first 2 characters of string another styling

Is it possible to style the first 2 characters of a message another styling?
::first-letter
Does not do the trick, also looked at this question, but this only hides the other ones.
Is it perhaps possible with the new pseudo elements? Or use the ch in combination with ::first-letter?
This is what I want to achieve but I have no clue how to do it with pure CSS.
NOTE, I can not change the HTML.
<h4 class="date">10 Mar. 2022</h4>
This can't be done with pure CSS since there is no way of (dynamically) selecting the first 'word'.
Consider a javascript alternative that wraps the first part in an <em></em> that can be styled with some CSS.
const e = document.querySelector('.date');
const t = e.innerHTML.split(' ');
e.innerHTML = `<em class='up'>${t.shift()}</em> ${t.join(' ')}`
.up {
color: darkblue;
font-size: x-large;
position: absolute;
top: 5px;
font-style: unset;
}
h4 {
color: lightblue;
margin-top: 30px;
}
<h4 class="date">10 Mar. 2022</h4>
You can use a mixture of JS and css to achieve what you are looking for.
First, just split the different parts (day/month/year) into different spans and add styling accordingly. An example as follows.
var text = $('.date').text();
var textArr = text.split(/\s+/);
$('.date').html(`<span class="day">${textArr[0]}</span>
<span class="month">${textArr[1]}</span>
<span class="year">${textArr[2]}</span>`);
.month {
color: red;
}
.day {
color: blue;
}
.year {
color: green;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<h4 class="date">10 Mar. 2022</h4>

Scale font to size when text exceeds container?

I want font size to be 54px if the text fits inside the container, otherwise it should be 36px.
I was considering whether I can achieve this with a pure CSS solution, using the scale function to collapse to either of the two. If the container can be assumed to be full with, I guess I could use vw as a base for a calculation?
But I am very much stuck on this. Could anyone give me a hint, as to how I can achieve this or something close to it.
If you would like to put some text inside a container and have it size itself to fill that container, then CSS Tricks has an article on Fitting Text to a Container that will cover your options.
You could also use Viewport Sized Typography which take advantage of viewport units such as:
1vw = 1% of viewport width
1vh = 1% of viewport height
1vmin = 1vw or 1vh, whichever is smaller
1vmax = 1vw or 1vh, whichever is larger
One unit of any v* is 1% of the viewport axis. Where the “Viewport” == browser window size == window object. If the viewport is 50cm wide, 1vw == 0.5cm. Using viewport units alone such as font-size: 4vw; can make the text appear too big or too small when varying the window width and bring accessibility issues (as the user preferences are not taken into account).
Lastly, you could use clamp() to achieve Simplified Fluid Typography. Clamp takes three values, a min, max, and a flexible unit in the middle that it will use in case the value is between the min and max.
If you want the font size to be a minimum of 36px and maximum 54px, you could use clamp() like this and vary the "flexible unit" to your liking. Here is an example of fluid typography for an <h1> element inside a container.
body {
font-size: 1rem;
margin: 0 auto;
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.container {
border: .2rem solid #f06;
padding: .5rem;
height: 100%;
width: auto;
}
.container h1 {
font-size: 36px; /* fallback */
font-size: clamp(36px, 10vw, 54px);
}
<body>
<div class="container">
<h1>Heading text</h1>
</div>
</body>
Browser support for clamp() is pretty good, but you’d probably want to put a font-size declaration before it to set an acceptable fallback value.
In conclusion, if you needed to set an explicit width and height for said container, you might want to use media queries along with viewport units, calc(), or clamp() depending on the size of the content box in which the text resides.
i think it's nearly impossible to calculate it without js.
below is an code example how i would do it in jquery or you could use the following jquery plugin, but i never tested this plugin before: FitText.js
for (let container of $('.text-container')){
container = $(container);
let textInner = $(container).find('.text-inner');
console.log(container.width());
console.log(textInner.width());
if (container.width()<textInner.width()){
textInner.addClass('fs-36');
textInner.removeClass('fs-54');
} else {
textInner.addClass('fs-54');
textInner.removeClass('fs-36');
}
}
.text-container,
.text-container-before{
position: relative;
width: 250px;
height: 60px;
background: #333;
color: #090;
overflow: visible;
margin: 20px 0;
}
.text-inner,
.text-before{
position: absolute;
top: 0;
left: 0;
height: 100%;
background: #0399;
word-break: keep-all;
white-space: nowrap;
}
.fs-54{
font-size: 54px;
}
.fs-36{
font-size: 36px;
}
/* just added because console window is hiding running code snipped */
.spacer{
height: 80px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<h1>before</h1>
<div class="text-container-before">
<div class="text-before fs-54">a bit longer text</div>
</div>
<div class="text-container-before">
<div class="text-before fs-54">shorter text</div>
</div>
<h1>after</h1>
<div class="text-container">
<div class="text-inner fs-54">a bit longer text</div>
</div>
<div class="text-container">
<div class="text-inner fs-54">shorter text</div>
</div>
<div class="spacer"></div>
This question awsers was not exactly what I was looking for, so here is a solution to scale down the text if it would exceed the size of the parent container, by making it smaller until it fits the container.
for(const element of document.getElementsByClassName("shrink"))
{
var size = parseInt(getComputedStyle(element).getPropertyValue('font-size'));
const parent_width = parseInt(getComputedStyle(element.parentElement).getPropertyValue('width'))
while(element.offsetWidth > parent_width)
{
element.style.fontSize = size + "px"
size -= 1
}
}
.container{
border:1px dashed #ccc;
display:flex;
align-items:center;
justify-content:center;
width:200px;
height:50px;
margin:10px;
}
.shrink{
white-space: nowrap;
font-size:80px;
}
<div class="container"><span class="shrink">long text to shrink</span></div>
<div class="container"><span class="shrink">small text</span></div>
try word-break: break-all;, I think this will solve your problem
Not, Sure about CSS solution. But, My JS solution can resolve your problem.
Refer below code. Class class-54 and class-36 will change based on content:
// creating node
function createNode(element) {
return document.createElement(element);
}
// creating append
function append(parent, el) {
return parent.appendChild(el);
}
var getPageTitle = document.getElementById("pageTitle"),
textLengthWidth = 0;
const getPageTitleText = getPageTitle.textContent;
getPageTitle.innerHTML = "";
for (let index = 0; index < getPageTitleText.length; index++) {
const span = createNode("span");
span.innerHTML = getPageTitleText.charAt(index);
append(getPageTitle, span);
if (index == getPageTitleText.length - 1) {
calcFontSize();
}
}
function calcFontSize() {
var listOfSpan = document.querySelectorAll("#pageTitle span");
listOfSpan.forEach(element => {
textLengthWidth += element.offsetWidth;
});
console.log("total DIV width: " + getPageTitle.offsetWidth);
console.log("total Content width: " + textLengthWidth);
getPageTitle.offsetWidth < textLengthWidth ? getPageTitle.classList.add("class-36") : getPageTitle.classList.add("class-54");
}
* {
padding: 0;
margin: 0;
font-size: 14px;
}
.title {
display: block;
width: 100vw;
}
h1, h1 span {
font-size: 54px;
}
.class-54 span {
font-size: 54px;
}
.class-36 span {
font-size: 36px;
}
<div class="title">
<h1 id="pageTitle">Hello World! Hello World!</h1>
</div>
Try this
.thingy {
font-size:54px;
overflow-wrap: break-word;
}
<h1 class="thingy">Hel000000000000000000ooo</h1>

Add a text suffix to <input type="number">

I currently have a number of inputs like this:
<input type="number" id="milliseconds">
This input field is used to represent a value in milliseconds.
I do however have multiple number inputs which take a value in dB or percentages.
<input type="number" id="decibel">
<input type="number" id="percentages">
What I would like to do is add a type suffix to the input field to let users know what kind of value the input represents. Something like this:
(This image is edited to show what result I want to have,I hid the up and down arrows from the input type as well).
I have tried to Google this but I can't seem to find anything about it. Does anyone know if this is possible, and how you can accomplish something like this?
You can use a wrapper <div> for each input element and position the unit as a pseudo element ::after with the content of your corresponding units.
This approach works well for the absolute positioned pseudo elements will not effect the existing layouts. Nevertheless, the downside of this approach is, that you have to make sure, that the user input is not as long as the text field, otherwise the unit will be unpleasantly shown above. For a fixed user input length, it should work fine.
/* prepare wrapper element */
div {
display: inline-block;
position: relative;
}
/* position the unit to the right of the wrapper */
div::after {
position: absolute;
top: 2px;
right: .5em;
transition: all .05s ease-in-out;
}
/* move unit more to the left on hover or focus within
for arrow buttons will appear to the right of number inputs */
div:hover::after,
div:focus-within::after {
right: 1.5em;
}
/* handle Firefox (arrows always shown) */
#supports (-moz-appearance:none) {
div::after {
right: 1.5em;
}
}
/* set the unit abbreviation for each unit class */
.ms::after {
content: 'ms';
}
.db::after {
content: 'db';
}
.percent::after {
content: '%';
}
<div class="ms">
<input type="number" id="milliseconds" />
</div>
<hr />
<div class="db">
<input type="number" id="decibel" />
</div>
<hr />
<div class="percent">
<input type="number" id="percentages">
</div>
If you want to support browsers, that doesn't show these arrows at all, make use of #supports or media queries.
Another interesting approach would be to use a little of JavaScript in order to make suffix actually stick to the input text (which probably looks better):
const inputElement = document.getElementById('my-input');
const suffixElement = document.getElementById('my-suffix');
inputElement.addEventListener('input', updateSuffix);
updateSuffix();
function updateSuffix() {
const width = getTextWidth(inputElement.value, '12px arial');
suffixElement.style.left = width + 'px';
}
/**
* Uses canvas.measureText to compute and return the width of the given text of given font in pixels.
*
* #param {String} text The text to be rendered.
* #param {String} font The css font descriptor that text is to be rendered with (e.g. "bold 14px verdana").
*
* #see https://stackoverflow.com/questions/118241/calculate-text-width-with-javascript/21015393#21015393
*/
function getTextWidth(text, font) {
// re-use canvas object for better performance
var canvas = getTextWidth.canvas || (getTextWidth.canvas = document.createElement("canvas"));
var context = canvas.getContext("2d");
context.font = font;
var metrics = context.measureText(text);
return metrics.width;
}
#my-input-container {
display: inline-block;
position: relative;
font: 12px arial;
}
#my-input {
font: inherit;
}
#my-suffix {
position: absolute;
left: 0;
top: 3px;
color: #555;
padding-left: 5px;
font: inherit;
}
<div id="my-input-container">
<input type="number" id="my-input" value="1500">
<span id="my-suffix">ms.</span>
</div>
However, this is just a proof of concept. You will need to work on it a little further to make it production-ready, e.g. make it a reusable plugin.
Also, you will need to handle a case, where input element is getting overflowed.
If you have option to add elements to input then you can try this:
.container {
max-width: 208px; /*adjust it*/
margin: auto;
position: relative;
display: inline-block;
}
#milliseconds {
padding-right: 35px;
}
.ms {
position: absolute;
top: 0;
right: 10px;
}
<div class="container">
<input type="text" id="milliseconds">
<span class="ms">ms</span>
</div>
I have a case where the design team wants the suffix to float with the values. We are using a custom font with very uneven number widths. I came with an idea to use a ghost to follow the input width and clamp the overflow with max-width by using a wrapper element. This is still a bit work in progress and glitchy (no initial fill, etc.).
const fillBuffer = (e) => {
// Clear the buffer if input gets wiped
if (e.target.value.length === 0) {
e.target.parentElement.querySelector('.suffix span').textContent = "";
return;
}
// Using a filler char will prevent the suffix to be overwritten with the input
const extraFiller = e.target.value.length ? '1' : '';
e.target.parentElement.querySelector('.suffix span').textContent = e.target.value + extraFiller;
}
// Attach the listeners
document.querySelectorAll('input').forEach((el) => {
el.addEventListener('keydown', fillBuffer);
el.addEventListener('keyup', fillBuffer);
});
* {
font-size: 1em;
font-family: Papyrus, sans-serif;
box-sizing: border-box;
}
body {
padding: 1em;
}
.input-wrapper {
margin-bottom: 0.5em;
}
.input-wrapper.with-suffix {
position: relative;
max-width: 150px;
overflow: hidden;
}
.input-wrapper.with-suffix input {
margin: 0;
width: 100%;
outline: 0;
padding-left: 4px;
padding-right: 16px;
}
.input-wrapper.with-suffix .suffix {
position: absolute;
padding-left: 6px;
top: 2px;
pointer-events: none;
width: 100%;
}
.input-wrapper.with-suffix .suffix span {
user-select: none;
pointer-events: none;
}
.input-wrapper.with-suffix .suffix .filler {
display: inline-block;
white-space: pre; /* Allow more than two whitespaces to be rendered */
color: rgba(0, 0, 0, 0.0);
background: rgba(255, 0, 0, 0.3);
max-width: calc(100% - 16px);
}
<div class="input-wrapper with-suffix">
<input type="text" value="5000">
<div class="suffix"><span class="filler">5000</span><span>€</span></div>
</div>
<div class="input-wrapper with-suffix">
<input type="text" value="5000">
<div class="suffix"><span class="filler">5000</span><span>€</span></div>
</div>

How to give a span or div the smallest size that will just fit its text content?

For example, in this simulated rendering, the orange background indicates the extents of the enclosing span or div element that just encloses all the contained text:
If that's too much to hope for, then a second best would be something like this:
In this second case the locations of the top and bottom edges coincide with the text's baseline and mean line.
At the absolute very least, I'd love to learn how to reliably line up the bottom of a span or div so that it is perfectly flush against the text's baseline. Even this seemingly straightforward task is beyond my reach. (My success rate is about 50%, and AFAICT entirely random.)
Below I show my best attempts so far. My results are terrible for the most part. It is true that for one font I get pretty close to the second case shown above, but I suspect this is just a lucky coincidence, judging by how poorly the same CSS fares with other fonts.
Code snippet below (or jsFiddle). Click on Full Page for best results.
* { vertical-align: baseline !important; }
#root { padding: 20px; }
td { padding: 0px; }
.monospace { font-family: monospace; }
.proportional { font-family: tangerine; }
.ground { padding: 10px; }
.ground > * { margin: 10px; }
.ground > * { font-size: 50px; }
.ground > * { background: orange; }
.ground > * { display: inline-block; }
.tweak-heights
.ground * { height: 1ex; }
.tweak-heights
.ground * { line-height: 0; }
.tweak-heights
.ground > * { margin: 20px 10px; }
<link rel="stylesheet" type="text/css" href="http://fonts.googleapis.com/css?family=Tangerine">
<div id="root">
<div style="display: block; width: 100%; text-align: right;"><div style="display: inline-block; margin: 0 50px 0 0;">(Click on FULL PAGE for best results.)</div></div>
<table>
<tr><td>
<div class="ground">
<span class="q monospace">Smallest SPAN 0123456789</span><br/>
<span class="q proportional">Smallest SPAN 0123456789</span><br/>
</td></tr>
<tr><td class="tweak-heights">
<div class="ground">
<span class="q monospace">Smallest SPAN 0123456789</span><br/>
<span class="q proportional">Smallest SPAN 0123456789</span><br/>
</td></tr>
</table>
</div>

Styling email link / href="mailto:" with CSS

Thanks to StackOverflow I finally found a way to style my email link, but I wonder why it doesn't work without the solution I found on here.
Since the link is part of the span with the attributed class "about", which has font size and style defined, shouldn't the email link show up in 11px and sans serif?
and while
a[href^="mailto:"]
{
font-family: sans-serif;
color: black;
font-size: 11px;
}
works great, as soon as i try to change it into
.about a[href^="mailto:"]
{
font-family: sans-serif;
color: black;
font-size: 11px;
}
it does not function as it's supposed too.
do tags not listen to span formatting or class nesting?
<!DOCTYPE html>
<html>
<head>
<style type="text/css">
html {
height:100%;
}
body {
height: 100%;
margin-left: 20px;
margin-top:0px;
}
.bottom-left {
position: absolute;
font:sans-serif;
bottom: 15px;
left: 15px;
}
.bold {
font-family: serif;
}
.about {
font-size: 11px;
font-family: sans-serif;
}
/*a[href^="mailto:"]
{
font-family: sans-serif;
color: black;
font-size: 11px;
}*/
.address {
font-size: 11px;
border-bottom: 1px grey dotted;
}
</style>
<title>TEMP</title>
</head>
<body>
<div class="bottom-left">
<span class="about">
<span class="bold">XYZ</span> is a project space . |
<span="address">Website Information</span> — info#info.eu
</span>
</div>
</body>
</html>
Hi actually you have commented your email link css:-
so now write the css like this method its working fine......
a[href^="mailto:"]
{
font-family: sans-serif;
color: red;
font-size: 11px;
}
see the demo:- http://jsbin.com/ijofoq/edit#html,live
UPDATED
Now its working fine...edit your HTML and add in your HTML
<div class="bottom-left">
<div class="about">
<span class="bold">XYZ</span> is a project space . |
<span="address">Website Information</span> — info#info.eu
</div>
basically you have to remove the span tag from .about class.
check this :- http://jsbin.com/ijofoq/2/edit
I think .about take precedence over a.
cf. Css Rule Specificity.
Basically, a css ruleset is assign a priority like a version number like this:
{#id}.{#class}.{#element}.{order}
with
{#id} : count of id selectors
{#class} : count of classes, pseudo-classes, attributes
{#element} : count of elements, pseudo-elements
{order} : the index of this rule across all files
So, we have the following order:
0.2.1.* .about a[href^="mailto:"] (0 id, 1 class + 1 attr, 1 element)
0.1.1.a span.about (0 id, 1 class, 1 element)
0.1.1.b a[href^="mailto:"] (0 id, 1 attr, 1 element)
0.1.0.* .about (0 id, 1 class, 0 element)
span.about and a[href^="mailto:"] have same specifity (1 class or attribute, and 1 element), so the order is important, the last wins.
If you remove the span then the rule is less specific and loose.
(Also, distinguish between rules directly applied to an element, and other inhertited from parent elements...)

Resources