Alignment of absolute child based on the baseline

I am currently working on creating a comprehensive Unicode table that allows for the comparison of glyph spacing among different fonts.

The goal is to have a table where users can select various fonts, each with their own unique metrics. Given this variability in font characteristics, I am exploring whether it is feasible to align the child fonts with the baseline of the parent font after positioning the child glyph objects absolutely.

#table{
  display: flex;
        justify-content: center;
        align-items: center;
  font-size: 72pt;
  /* reference dimensions */
  border: 1px solid blue;
}

#table > div {
  display: inline-flex;
        justify-content: center;
  font-family: sans-serif;
  border: 1px solid #F0F;
}

#table > div > span {
  position: absolute;
  mix-blend-mode: difference;
  font-family: monospace;
  color: green;
  /* alignment reference */
  outline: 1px solid #0F0;
}
<div id="table">
  <div>x</div>
  <div>y</div>
  <div>z</div>
  <div>!</div>
</div>

My ideal solution would involve using solely CSS, although my research suggests this may not be achievable. Is there any way to access and manipulate font metrics through JavaScript, perhaps by calculating margins based on top or bottom values and passing them as CSS variables?

If an alternative approach is required, I may end up adjusting the relative position of child glyphs towards the start of the flex container by half their width plus half the width of the parent object. This could become cumbersome when dealing with thousands of glyphs and frequent font changes...


UPDATE: To provide context, the fonts "Arial" and "Times New Roman" are utilized as sans-serif and monospace respectively. The initial output is tested in Gecko/Firefox and later aligned with Chromium. While minor discrepancies between browsers may not usually pose a problem, these differences can impact specific layout aspects. For example, the default baselines in Word appear as shown below:

https://i.sstatic.net/Y8JwY.png

  • In "Times New Roman", the 'z' and '!' characters extend below the baseline, similar to the right side of 'x'.
  • The character 'y' actually extends above the baseline slightly.
  • All glyphs exhibit greater ascenders and descenders compared to their counterparts in "Arial".

Answer №1

One way to achieve this effect is by wrapping each "letter" in its own div element. Then, you can set both the main span and the child span to have a position of absolute and align them at the bottom to ensure they share the same baseline.

To create some spacing between the letters, you can add a margin to the new divs. You can see an example of how this can be done below:

#box{
  display: inline-block;
        justify-content: center;
        align-items: center;
  font-size: 72pt;
  /* dimension ref */
  border: 1px solid blue; 
}

#box > div {
  position: relative;
  height: 100px;
  display: inline-block;
  margin: 30px;
}

#box > div > span {
  display: inline-flex;
        justify-content: center;
  font-family: serif;
  border: 1px solid #F0F;
  position: absolute;
  bottom: 0;
}

#box > div > span > span {
  position: absolute;
  mix-blend-mode: difference;
  font-family: cursive;
  color: red;
  /* alignment ref */
  outline: 1px solid #0F0;
  bottom:0;
}
<div id="box">
<div><span>x<span>x</span></span></div>
<div><span>y<span>y</span></span></div>
<div><span>z<span>z</span></span></div>
<div><span>!<span>!</span></span></div>
</div>

Answer №2

It seems I may have overlooked a simple solution: setting the letter-spacing to -1em for the parent glyph eliminates the need for absolute positioning of the child glyph while keeping the original inline baseline intact. There's no necessity for flex on the glyph parent either.

An added advantage is that now the outlines adhere to the specific font dimensions instead of being uniformed by flex and absolute positioning.

(It should be noted that mix-blend-mode is crucial to my goal, although it doesn't seem to work in the snippet console for text, only within the box model. Feel free to use your imagination or test it elsewhere. Highlighting the text in the snippet result will demonstrate the desired effect.)

div#box {
  font-size: 72pt;
  letter-spacing: -1em;
  /* box ref */
  outline: 1px solid #F0F;
}

#box > span {
  font-family: serif;
  /* dim ref */
  outline: 1px solid #000;
}

span > span {
  mix-blend-mode: difference;
  font-family: cursive;
  color: #0FF;
  letter-spacing: 0em;
  /* dim ref */
  outline: 1px solid #0FF;
}
<div id="box">
  <span>x<span>x</span></span>
  <span>y<sЛюT°jXÆ׏ɸۖКj@SPtzH6̳ئN5~ҰJ%
    ĮʺvȊǻ^ǩdԒMU*tCw)ߝ][!<span>!</span></span>

</div>

A rare instance where em behaves as expected rather than unexpectedly quirky.

Answer №3

Adjust the box position to be relative and then manage the positioning of absolute children using px or %

#box{
    display: flex;
          justify-content: center;
          align-items: center;
    font-size: 72pt;
    /* dimension ref */
    border: 1px solid blue;
    position: relative;
  }
  
  #box > span {
    display: inline-flex;
          justify-content: center;
    font-family: serif;
    border: 1px solid #F0F;
  }
  
  #box > span > span {
    position: absolute;
    mix-blend-mode: difference;
    font-family: cursive;
    color: red;
    /* alignment ref */
    outline: 1px solid #0F0;
    bottom: 1%;
  }
 <div id="box">
    <span>x<span>x</span></span>
    <span>y<span>y</span></span>
    <span>z<span>z</span></span>
    <span>!<span>!</span></span>
  </div>

Place them on the side

#box{
    display: flex;
          justify-content: center;
          align-items: center;
    font-size: 72pt;
    /* dimension ref */
    border: 1px solid blue;
    position: relative;
  }

  #box > span {
    display: inline-flex;
          justify-content: center;
    font-family: serif;
    border: 1px solid #F0F;
    position: relative;
    width: 70px;
    margin-right: 50px;
  }

  #box > span > span {
    position: absolute;
    mix-blend-mode: difference;
    font-family: cursive;
    color: red;
    /* alignment ref */
    outline: 1px solid #0F0;
    bottom: -1%;
    left:  70px;
    width: 50px;

  }
 <div id="box">
    <span>x<span>x</span></span>
    <span>y<span>y</span></span>
    <span>z<span>z</span></span>
    <span>!<span>!</span></span>
  </div>

EDIT: in response to your comment:


in that case, it might be more effective to group letters in a single container, and then position both of them absolutely with baseline alignment. The example below illustrates this without additional positioning adjustments related to the font baseline. You can fine-tune the positioning using bottom

#box{
  display: flex;
  justify-content: center;
  align-items: baseline;
  font-size: 72pt;
  /* dimension ref */
  border: 1px solid blue;
  position: relative;
  height: fit-content;
  padding: 100px;
}

.black {
  position: absolute;
  display: flex;
  text-decoration: underline;
  
  justify-content: center;
  font-family: serif;
  border: 1px solid #F0F;
  letter-spacing: 30px;
}

.red {
  display: flex;
  text-decoration: underline;
  position: absolute;
  mix-blend-mode: difference;
  font-family: cursive;
  color: red;
  border: 1px solid lightgreen;
  letter-spacing: 30px;
 
}
<div id="box">

    <div class="black">XYZ!</div>
    <div class="red">XYZ!</div>
   
  </div>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Using jQuery to transfer the selected value from one radio button to another

I am attempting to transfer all input data from one div to another div containing the same inputs, triggered by a checkbox selection. This is the structure of my HTML Form: <div id="0">Name* <input type="textbox" name="name0" required/>S ...

Finding the Xpath for an element that contains only a span tag, with identical attributes except for the text within

I am struggling to find the xpath for a button element that says 'Cancel'. <div class="uipresk"> <button class="something" role="button" type="button"> <span class="thisthing">OK</span> </button> ...

Downloading xml data in an Angular table is a straightforward process that can be achieved

I have a table displaying a list of data. Each row includes an option to download XML data. 0{ firstName: null id: "04674" lastName: null orderId: "TEM001" productId: "TEM" receiptPeriod: "2016-02-26" ...

Advanced Techniques: Leveraging Master Layouts, Partial Rendering, and JavaScript Function

Trying to understand the sequence of events when a master page, partials, and JavaScript code are involved. Imagine having a Master page with scripts: <%@ Master Language="C#" ... %> <head> <asp:ContentPlaceHolder ID="HeadContent" run ...

The image source failed to load the image using the function

Initially, I set up a sandbox to work on this issue: https://codesandbox.io/s/naughty-almeida-u66mlt?file=/src/App.js The main problem arises when the requested image fails to display after the function is called and the URL is returned. Here are my atte ...

Organize the outcomes according to the date provided by the object's keys, and simply tally the number

Hello, I am struggling to retrieve a complex return using MongoDB and Javascript. Can someone please explain how to achieve this? Admin. Group the result by ID. User: Flatten the result. Here is an example of the data: let user = [ { _id: 123, ...

Leveraging the power of CSS id selectors to customize the appearance of a Grid

In my current CSS file, I have defined two id selectors: #TableHead { font-family: Arial, Helvetica, sans-serif; font-size:11px; font-weight: bold; color: #000000; border-top-width: thin; border-top-style: solid; border-top-color: #A9AAAA; border-bottom-w ...

Oops! Looks like we have encountered an issue with reading the property 'checked' of nothing

Whenever I click the checkbox, an image should be displayed. Unfortunately, I encountered an error: Uncaught TypeError: Cannot read property 'checked' of null at (index):185 at dispatch (VM576 jquery.min.js:3) at i (VM5 ...

Incorporating a file from a specific directory in AngularJS

Every time I execute /sites/all/themes/theme/js/controller.js $scope.template = 'partials/tpl.html' /sites/all/themes/theme/js/index.html <div ng-include='template'></div> /sites/all/themes/theme/js/partials/tpl.html & ...

display a dual-column list using ngFor in Angular

I encountered a situation where I needed to display data from an object response in 2 columns. The catch is that the number of items in the data can vary, with odd and even numbers. To illustrate, let's assume I have 5 data items to display using 2 co ...

Issues with Navigating through a Scrollable Menu

I'm having a difficult time grasping the concept and implementing a functional scrolling mechanism. Objective: Develop a large image viewer/gallery where users can navigate through images by clicking arrow keys or thumbnails in a menu. The gallery an ...

Create a regular expression to identify and substitute incorrect HTML properties

It's a harsh reality that my regex skills are lacking. Upon revisiting an old project, I stumbled upon some code that definitely needs attention. Take a look: strDocument = strDocument.Replace("font size=""1""", "font size=0.2") strDocument = strDocu ...

socket.io fails to transmit information

I am working on a chat application that includes a user list feature. To send the user list to each user upon connection, I am performing the following actions from the server : io.on('connection', function (socket) { var users = []; ...

Using Vue.js, you can bind a JSON object as the value of a checkbox input to the

Can a Json Object be passed as a value on a checkbox? I have multiple checkboxes as shown below... selectedUsers is an array containing the selected values... I would like to end up with a json array like [{"userid": "12345"}, {"userid": "54321"}] <inp ...

Instructions on exporting a CSV file from a JSON array with Node.js

How can I convert a JSON array into a CSV file using Node.js? The JSON data needs to be formatted with only three columns: Column A for total number of responses, Column B for Name, and Column C for field1. Below is the code snippet I am currently using: ...

Tips for getting rid of the ghosting effect or white background of a PNG image

As a new developer, I am currently working on my personal chess project and have recently mastered the drag and drop system. However, I would like to explore different methods for achieving this. Is there a way to eliminate the white background in the proc ...

"Encountering a RangeError with Node.js Sequelize while working with

I need some assistance with using Sequelize in my Node.js application paired with MySQL. When I try to execute the command npx sequelize db:create, I encounter an error that I do not know how to resolve. Any guidance on this matter would be greatly appreci ...

Is there a way to apply a consistent border to both the input radio button and its corresponding label once the radio button has been selected

CSS: <div class="form-check fs-3 mb-3"> <input id="first_question" name="first_question" type="radio" value="n"> <label for="first_question">no</label> </div> Is ...

Tips for incorporating "are you sure you want to delete" into Reactjs

I am currently working with Reactjs and Nextjs. I have a list of blogs and the functionality to delete any blog. However, I would like to display a confirmation message before deleting each item that says "Are you sure you want to delete this item?" How ...

Determine the number of visible li elements using jQuery

Currently, I am utilizing a jQuery script to count the number of li elements in my HTML code. Here is an example of the setup: HTML: <ul class="relatedelements"> <li style="display:none;" class="1">anything</li> <li style="disp ...