Determining height and length of text in pixels given the font - html

This is mostly an HTML question, but I am interested in extracting information from the HTML using Python 3.
My question is:
Given a font-family, font-weight, and font-style, as well as the text itself and the text-size, how can I determine the height and width of the text?
Namely, I have the coordinates of the upper left corner of the text, and I would like to find its lower right corner. I am ready to manually input the sizes of single letters in my script, if that's what it takes (hopefully not!).
As a base example, I have a font
f { font-family:sans-serif; font-weight:normal; font-style:normal; }
and a tag
<span id="f" style="font-size:20px;vertical-align:baseline;color:rgba(0,0,0,1);">Hello, world!</span>
I would like to calculate the width and height of the text, in pixels.
I am aware of related questions on the site, but I couldn't find any that would answer my specific question. Feel free to link such a question (if answered), if it exists.

I have a workaround solution to this (not implemented yet). The parsing of the fonts is (often) done through referral to a .ttf (TrueFont) file. You can find such files in C:/Windows/Fonts (in Windows, not sure about other OS).
Using PIL/Pillow in Python, you can draw the bitmap of any string in a given font, see e.g. this answer. To be exact, you want to use PIL.ImageFont.ImageFont.getmask after initialising an instance of ImageFont with the appropriate .ttf file. Then you can just get the size of the mask and rescale to match the font size.

Related

Why is 50vw font-size not 50% of the actual viewport? [duplicate]

I am trying to find what the value set in the font-size CSS property is corresponding to.
To give the context, I want to get in CSS the size in em of parts of the font (above the capital height and under the baseline) that I know from its OS/2 metrics. The em unit is relative to the given font-size and the OS/2 metrics are relative to the em-square.
What I expect
My expectations are based on the following references. I did not found anything more clear or precise.
According to the W3C reference for font-size in CSS2.1, and as quoted in all the Stack Overflow questions I found on the topic (here, here and here):
The font size corresponds to the em square, a concept used in typography. Note that certain glyphs may bleed outside their em squares.
Following the few knowledges I have in typography, the em square is the entire square of font metrics in which ascending, descending, gaps, (etc...) lines are defined. In OS/2 metrics, the em square is the size of the font itself (often 1000 or 2048 UPM).
(source: microsoft.com)
The only explanation I found from W3C is in an old reference from 1997 for CSS1, and it is coherent with the modern digital definition of em square I use:
Certain values, such as width metrics, are expressed in units that are relative to an abstract square whose height is the intended distance between lines of type in the same type size. This square is called the EM square. (...) Common values are 250 (Intellifont), 1000 (Type 1) and 2048 (TrueType).
So if I understand these references correctly, the value specified in font-size should be used to generate the entire em square of the font, and we should be able to calculate the size of a part of the font from the font's size and metrics.
For example, with...
.my-letter {
font-family: 'Helvetica Neue';
font-size: 100px;
text-transform: uppercase;
}
... we should have an em square of 100px, and because Helvetica Neue has a Capital Height of 714 / 1000 (sCapHeight in the OS/2 table), a capital height of 71.4px.
What actually happens.
The generated em square is bigger than font-size (tested on the latest versions of Chrome, Firefox and Safari for Mac). At first, I thought that the browser had an other definition of em square and was making a part of the letter equal to font-size, but I did not found any OS/2 metrics (with or without ascender, descender, gaps...) that matches with it.
You can also see this CodePen. Please note that I use line-height: 1; to highlight the expected size, but my problem is with font-size (the "rendered ink") and not line-height (the "collision box"). This is something I have to precise because I have already been misunderstood several times. line-height is not the problem.
So I have three questions:
Did I understood correctly the W3C references, or I am assuming things that these references did not said?
If not, why does the generated font have an em-square greater than font-size?
The most important: How could I know the size of the rendered em-square (relatively to the font-size) ?
Thank you for your help.
Your understanding of the W3C references is correct, but your understanding of the red box is not.
The red box does not depict the em-square. Its height is the sum of the ascent and descent from the metrics.
The article (that had been shared in a now deleted answer) explains it very well. This is my attempt to turn it into a stand-alone answer.
Let's assume we have a <span> styled with the font-family: Roboto and font-size: 48px and we want to answer the seemingly simple question: What is the effective height of the span? Spoiler: It is 65px. This is how you could derive it:
First you need to know some metrics about the font. If you are on Linux you could inspect the font with FontForge like so:
$ fc-list | grep Roboto
$ fontforge /usr/share/fonts/truetype/roboto/hinted/Roboto-Regular.ttf
Under Element => Font Info... => General you can get the Em Size which is kind of like a unitless base unit of the font:
Under Element => Font Info... => OS/2 => Metrics you can find the ascent/descent, which are the largest extensions of the font:
What the browser does is to match the em size (2048) with the specified font size (48px). Based on that, it computes how big the area covered by the ascent/descent (2146, -555) is in relation to the em size. So the formula is roughly:
result_size = (ascent + |descent|) / em_size * font_size
In this example:
(2146 + 555) / 2048 * 48px = 63.375px
The remaining question is why the browser actually arrives at 65px instead. My assumption is that the ascent and descent get rounded up individually. Applying the formula individually gives 50.30px => 51px for the ascent and 13.01px => 14px for the descent, resulting in exactly 65px.

Is there any difference between user units and pixels?

I've been reading several articles about SVG that make a clear distinction between using and not using units (this last case even has a name of its own), e.g.
<!-- the viewport will be 800px by 600px -->
<svg width="800" height="600">
<!-- SVG content drawn onto the SVG canvas -->
</svg>
In SVG, values can be set with or without a unit identifier. A
unitless value is said to be specified in user space using user units.
If a value is specified in user units, then the value is assumed to be
equivalent to the same number of “px” units. This means that the
viewport in the above example will be rendered as a 800px by 600px
viewport.
You can also specify values using units. The supported length unit
identifiers in SVG are: em, ex, px, pt, pc, cm, mm, in, and
percentages.
source
Is there any actual difference between omiting the unit and setting it to px?
Can I just set e.g. mm everywhere to avoid ambiguity, or I'll eventually be getting different results?
<svg width="800mm" height="600mm">
Disclaimer: what follows is pure guessing (I only learnt the basics of SVG last week) but I'm sharing it because I believe it could help others with my same doubts and I hope it doesn't contain serious errors.
The SVG canvas is basically a mental concept—a infinite plane where you use Cartesian coordinates to place stuff and move around. It isn't too different from stroking shapes in a sheet of graph paper where you've drawn a cross to identify an arbitrary point as coordinate origin, except that notebooks are not infinite. In the same way that tou draw a 3-square radius circle in the sheet and you don't care that those squares represent 12 mm, you draw shapes in your SVG canvas using unitless dimensions because it doesn't really matter what exact physical size they represent. The SVG spec uses the term "user units" to express this idea.
Using actual units only makes sense in two situations:
When our virtual user units need to interact with real world, e.g., the canvas is to be printed in a computer monitor.
When we want an element in our graph to be defined in such a way that it doesn't scale, neither up nor down, e.g. a stroke around a letter that needs to look identical no matter how we resize the logo it belongs to.
It's in this situation, more specifically #1, when the px equivalence comes in handy. When we need to render the graph or make calculations what involve actual units, unitless dimensions are interpreted as pixels. We can think of it as a default because we can render the canvas any size and, in any case, pixels are no longer physical pixels in these days of high-res displays and builtin zoom.
And, for all this, it's probably better to just omit units in your SVG code. Adding them in a general basis only makes code unnecessarily verbose.

Increasing/Decreasing font size on button click

I am sure you guys must have seen that font resizing option on some website where they display alphabet "A" in small, medium and large sizes clicking on which changes the font size of website. I have two questions:
What is that thing called actually? Like if there is a term to describe it?
What arguments can I give against using this on website? One of the client has asked to incorporate it in website and I don't see any real benefit in using it so what arguments can I give to client against using it?
It is called "font size change options", or "font resizer".
Here is a simple and minimal 5 lines of code jQuery tutorial: http://www.programming-free.com/2013/12/increase-decrease-font-size-jquery.html
A bit of the code that enlarges the font size:
newFontSize= parseInt($('#content').css('font-size')) + 2;
$('#content').css('font-size', newFontSize);
The user could just use CTRL+ in browser. The problem is that the final user doesn't know this trick.
This is a fast and simple implementation, no need to convince the client against it. I find myself getting hard to see clear small text after 10 hours of programming. Maybe the client has sight problems and needs to address others like him.
"As of jQuery 1.6, .css() accepts relative values similar to .animate(). Relative values are a string starting with += or -= to increment or decrement the current value. For example, if an element's padding-left was 10px, .css( "padding-left", "+=15" ) would result in a total padding-left of 25px."
Reference
So to do that you can use a function callback which will return the actual value, then you return the new value.
Like the following.
$("#fontPlusBtn").click(function (){
$("#textDiv > *").css("font-size", function(i, value) {
return parseInt(value) * 1.1;
});
});
Working Demo for Increasing Font Size on Button Click:
I hope this helps you as you described font size change on Button Click.
What is the target group of your client? Adding such feature is generally considered good practice of web accessibility. It doesn't really take up too much space on the screen and doesn't mess with the design but gives users the options to enlarge the text in case they are having troubles reading the text.
I wouldn't try to argue against it but instead find a neat way to implement the functionality.
BBC's accessibility policy is a good read: http://www.bbc.co.uk/accessibility/best_practice/policy.shtml

display text as square symbols instead of letters

Is there a simple css way to display text with every letter replaced with a filled square?
My idea was to find a font-family that has squares for all letters, but I didn't find anything like that existing. Google is no friend as it gives hits of posted issues with boxes that appear when fonts fail in some way.
Letters should be displayed as squares, not replaced with squares. Also, I need to be able to control the square fill color with the usual html/css.
I'm fine to use font-face, but am trying to avoid the learning curve for creating my own font.
Update: here is an example:
div.innerHTML = "some arbitrary text".
Should be displayed like this:
"■■■■ ■■■■■■■■■ ■■■■".
#NoobEditor is right although. Many online font editors available (e.g.: http://fontark.net/farkwp/ ), you can create such font family in few minutes and can embed with your app.
Get a square font, define it in your we page style, asign it to an object, a div must work, put your text there. Voila.

How to measure the size of the text in specific font of specific font size

I would like to do a trimming of the text that I need to display in box on a web page.
The known parameters are Font Family, Font Size, the number of characters to display and the actual text and of course the width of bounding box.
I need to calculate where to trim the source text and where to put "..."
I have an idea but it is not too fast.
If there exist some other way to do the trimming maybe in CSS I would like to know it and I can accept it as a solution too.
You cannot calculate this ahead of time. You need to position the actual text in the browser and measure the output. You can do this off-screen using a negative text-indent if needed.
There are plug-ins for jQuery that can set an ellipsis based on a fixed-sized container with overflow.
See: http://archive.plugins.jquery.com/plugin-tags/ellipsis
So long as you don't need to support older browsers, you could use this simple css:
text-overflow:ellipsis;
http://www.w3schools.com/cssref/css3_pr_text-overflow.aspenter link description here