📜 ⬆️ ⬇️

Automated correction of indentation in layout based on typographic styles and text metrics

Indentation during layout and composition of elements on the page requires a certain skill to ensure the right combinations and the desired result.

And if in the design layout the requested indents are specified without taking into account the line height and empty font rendering areas (shoulders, diacritics, descending height)? How to make the layout as close to the layout as possible efficiently and without long manual recalculations? The leading and the vertical rhythm make it possible to unify the distances between the elements, but they do not solve the problem of compensating the distances, taking into account the text metrics of the fonts used.

When developing applications for luxury clients, special attention is paid to the accuracy of interface implementation, where each pixel is under control.
')
In this article, we will consider an approach designed to optimize the routine work around indents — an automated adjustment of indents, taking into account the height of the line of target elements and the text metrics of the fonts used during the pre- or post-compilation of styles.

Design Specification Requirement


And so, the distance between elements containing text from the baseline of one element to the upper limit of the capital letter (cap line) of the next element must be a certain value (for example: 24px), excluding the area of ​​accented characters and shoulders.

Design expectations

When using this value in such declarations as, for example, padding or margin - between the elements, an indent area is formed, containing:

  1. Directly specified indent values ​​(24px) between elements.
  2. (Above the indent) The distance between the baseline of the text (baseline) and the bottom border (bottom bearing line) of the bounding box of the font (font bounding box, b-box, bbox) is the height of the lower offset (descent height).
  3. (Above Indent) The distance between the lower bound of the bounding box of the font and the lower bound of the height of the element line (for example, 4px when specifying 16px / 1.5).
  4. (Indented) The distance between the upper limit of the line height and the upper bearing (top bearing line) of the bounding box of the font. For example, 4px when specifying 16px / 1.5).
  5. (Indented) The distance between the upper bearing line of the bounding box of the font and the line passing through the upper border of the capital letter (cap line), which includes the diacritic drawing area and shoulders.

(Font measurements)

Example


As an example, consider the implementation of a banner with the text:

<div class="banner"> <div class="banner__media"> <div class="banner__content"> <h2 class="banner__content-title">Men</h2> <p class="banner__content-description">Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text.</p> <ul class="banner__content-links"> <li> <a href="#">Women</a> </li> <li> <a href="#">Men</a> </li> <li> <a href="#">Boys</a> </li> <li> <a href="#">Girls</a> </li> </ul> </div> </div> </div> 

Typographic styles applied to the conventional project:

 /* Typography styles */ .type-h2 { font-family: Arial; font-size: 35px; line-height: 40px; font-weight: bold; text-transform: uppercase; letter-spacing: 2px; html[lang^="de"] & { font-family: 'Karla Bold'; font-size: 35px; line-height: 40px; } } .type-p1 { font-family: Arial; font-size: 16px; line-height: 22px; font-weight: normal; letter-spacing: 0; html[lang^="de"] & { font-family: 'Karla Regular'; font-size: 16px; line-height: 22px; } } @media only screen and (min-width: 480px) and (max-width: 767px) { .type-h2 { font-family: Arial; font-size: 50px; line-height: 55px; html[lang^="de"] & { font-family: 'Karla Bold'; font-size: 50px; line-height: 55px; } } .type-p1 { font-family: Arial; font-size: 16px; line-height: 22px; html[lang^="de"] & { font-family: 'Karla Regular'; font-size: 16px; line-height: 22px; } } } @media only screen and (min-width: 768px) { .type-h2 { font-family: Arial; font-size: 80px; line-height: 90px; html[lang^="de"] & { font-family: 'Karla Bold'; font-size: 80px; line-height: 90px; } } .type-p1 { font-family: Arial; font-size: 19px; line-height: 26px; html[lang^="de"] & { font-family: 'Karla Regular'; font-size: 19px; line-height: 26px; } } } 

(The font size and line height are redefined for the class of the header (.type-h2) and the paragraph (.type-p1) depending on the breakpoint and locale.)

As well as styles directly for the banner:

 /* banner.scss */ @import 'path/to/typography.scss'; .banner { display: flex; flex-direction: column; justify-content: flex-end; background: url('path/to/banner-image.png') no-repeat center bottom; background-size: cover; &__content { color: #fff; padding: 48px 0 48px 48px; &-title { @extend .type-h2; } &-description { @extend .type-p1; max-width: 80%; margin-top: 24px; } &-links { @extend .type-p1; display: flex; flex-direction: row; margin-top: 24px; li { margin-left: 18px; &:first-child { margin-left: 0; } a { color: inherit; } } } } } 

(For clarity, indentation areas are shifted to the visual borders of the elements.)

Result for English locale:

Locale

The result for the German locale (the title is changed from the English version to demonstrate the area of ​​diacritics) :

Rendered text without typography adjustment for german locale

As one would expect, the actually used indentation value (24px) was supplemented with empty areas of the height of lines and bounding boxes of the font, area for drawing diacritical marks, as well as area of ​​the descending type height.

To achieve the desired result, the following approaches were considered:

1. Reducing the height of the line of the text element.

Minuses:

- Not suitable for multi-line text, as it affects its leading.
- When dropping to the actual value of the font height leaves empty areas of the bounding box of the font - shoulders.

2. Offset to the “extra” height by using negative values ​​of indents directly of the text element (or its containing) or, as an alternative, its pseudo-element.

  .selector { margin-top: -6px; } .selector-2:before { content: ''; display: table; margin-top: -6px; } 

Minuses:


3. Reducing the size of the bounding box of the font to the limits of rendering the glyph, by modifying the font itself.

Minuses:


4. Reducing the value of the indent used to visually match the desired value.

Minuses:

  1. It requires calculation of the value depending on the typographic styles of the target and / or neighboring elements, depending on the typographic styles and text metrics of the font used.
  2. It requires specifying different values ​​when using dissimilar font families for different localizations, which means manually creating additional rules.
  3. Changing the basic typographic styles of the site and / or replacing fonts implies recalculation of the values ​​used (due to differences in the text metrics of the new font).
  4. The presence of additional rules for different localizations and / or media quieries implies manual creation and miscalculation of all possible combinations.

Of the listed ways to solve the presented problem, the most reliable and accurate, but at the same time the most time-consuming, is point 4.

For applications that support different breakpoints and several localizations, this means that it is necessary to accurately calculate the values ​​applied to the declarations used, as well as create additional rules that take into account media queries, localization selectors, and textual metrics of the fonts used. Pleasure, to put it mildly, is dubious. Moreover, the time spent on the description of exact styles and their subsequent verification increases the development time, adding the routine work to both developers and testers.

To automate the process of recalculating spacing between text elements based on typographical rules and text metrics of the fonts used, as well as automated support for all dependent combinations used in typographic styles, a postcss postcss-text-indentation-adjustment plugin was created

PostCSS postcss-text-indentation-adjustment plugin


postcss-text-indentation-adjustment is a postcss plugin that allows you to adjust the indent values ​​used in styles, taking into account typographic styles, as well as textual metrics of the fonts used.

Work algorithm:

1. Extract text metrics used in a font project.
2. Extract data from typographic styles used.
3. Initialize the plugin and include it in the build process.
4. Description of the correction of the declaration value using special syntax with typographical selectors.
5. Building the project and getting the result of adjustments with all possible combinations of external rules for typographic styles (media queries, parent selectors and their combinations).

Benefits:

  1. The original indent value is used (for example, from a design layout or a typographic style guide), which allows you to store these values ​​centrally in variables and, when changing the design of requirements, easily change the original values.
  2. The indentation value is adjusted to subtract the empty areas of the line height, the bounding box of the font, the area of ​​accent marks and the descending height of the font, using the values ​​of typographic styles for text elements for which the distance should be reduced.
  3. If there are several rules in typographic styles that depend on media queries (media-query) or specific parent selectors (for example, html [lang ^ = "de"], .parent-classname), the necessary additional rules are automatically created for the target declaration, whose value needs to be adjusted, taking into account media queries and / or parent selectors, as well as having calculated the final declaration values, taking into account the used line heights and text metrics of plug-in fonts.

An example of rules applied to a typographic headline style with a .type-h2 class describing the redefinition of a font family, as well as its size and line height for a particular screen width and German locale:

 .type-h2 { font-family: Arial; font-size: 35px; line-height: 40px; font-weight: bold; text-transform: uppercase; letter-spacing: 2px; html[lang^="de"] & { font-family: 'Karla Bold'; font-size: 38px; line-height: 46px; } } @media only screen and (min-width: 768px) { .type-h2 { font-family: Arial; font-size: 80px; line-height: 90px; html[lang^="de"] & { font-family: 'Karla Bold'; font-size: 86px; line-height: 94px; } } 

4. When using the css preprocessor (for example, sass, scss, less) - nesting of the processed rules is supported, as well as the use of variables.

The accuracy of plug-in adjustments depends on the textual font metrics that are passed as an argument at the time it is initialized, so before integrating the postcss-text-indentation-adjustment plugin into our example, consider how text metrics can be extracted.

Extract text metrics


The following method for extracting text metrics is arranged in a separate font-metrics package and allows you to get text metrics from locally saved, system or remotely located fonts, using the CSS Font Loading API , drawing text on canvas in Chrome with the “experimentalCanvasFeatures: true” flag enabled followed by saving the values ​​to a file.

To extract text metrics, we use the context method of the canvas measureText . According to the TextMetrics documentation , the only available value of the TextMetrics object when drawing in the browser is the width of the drawn text.

To solve our problem, more detailed parameters are needed, such as fontBoundingBoxAscent (the distance from the baseline to the upper bound of the bounding box of the font), fontBoundingBoxDescent (the distance between the baseline and the lower bound of the bounding box of the font), and alphabeticBaseline (the distance between the baseline chosen for drawing and an alphabetic baseline) and hangingBaseline (the distance between the baseline selected for the drawing and the upper bound of the glyph drawing without taking into account the area of ​​accented characters), available only in chrome om flag ExperimentalCanvasFeatures: true.

The sum of the fontBoundingBoxAscent and fontBoundingBoxDescent values ​​will give the actual height of the rendering area of ​​the font's bounding box, and the difference of the hangingBaseline and alphabeticBaseline values ​​will show the actual height of the capital letter (cap height) without accents, descending heights.

Since the values ​​are represented in CSS pixels and will be calculated relative to the font-size value used to draw the text - you can use the ratio of the difference between the height of the bounding box of the font and the height of the capital letter to the height of the capital letter. This will allow us to calculate the relative height of the excluded areas for the target font size used in our styles.

But first things first.

Chrome launch with ExperimentalCanvasFeatures flag


We will need an html page with a canvas created on it, available for our script.
To manipulate the canvas in the browser with the ExperimentalCanvasFeatures flag enabled, use the Nightmare library:

 import Nightmare from 'nightmare'; import fse from 'fs-extra'; const browser = Nightmare({ show: false, webPreferences: { experimentalCanvasFeatures: true } }); const pageUrl = 'your/path/to/canvas/page'; //  ,       const fontsData = { fonts: [{ fontFamily: 'Arial' }, { fontFamily: 'Karla Regular', src: '//fonts.gstatic.com/s/karla/v6/S1bXQ0LrY7AzefpgNae9sYDGDUGfDkXyfkzVDelzfFk.woff2' }, { fontFamily: 'Karla Bold', src: '//fonts.gstatic.com/s/karla/v6/r3NqIkFHFaF3esZDc3WT5BkAz4rYn47Zy2rvigWQf6w.woff2' }], fontSize: 24 }; browser.gotTo(pageUrl) .evaluate(data => { //              -  Promise return new window.Promise((rootResolve, rootReject) => { const {fonts, fontSize} = data; //    ,      ,      ,   Promise const fontsToLoad = fonts.reduce((result, fontData) => { const {src, fontFamily} = fontData; //    src  ,     if (typeof src === 'string') { return result; } const promise = new window.Promise((resolve, reject) => { //       FontFace const fontFace = new window.FontFace(fontFamily, `url(${encodeURI(src)})`); //    font face,     fontFace.load().then(function () { document.fonts.add(fontFace); resolve(); }).catch(function (err) { reject(err); }); }); return promise; }, []); const fontsMetrics = {}; //      -          window.Promise.all(fontsToLoad).then(() => { const canvas = document.getElementById('canvas'); const ctx = canvas.getContext('2d'); //         ctx.textBaseline = 'alphabetical'; fonts.forEach(fontData => { //         ctx.font = `${fontSize}px ${fontData.fontFamily}`; const metrics = ctx.measureText('Example'); fontsMetrics[fontData.fontFamily] = metrics; }); }); rootResolve(fontsMetrics); }); }, fontsData) .end() .then(result => { //         const content = JSON.stringify(result, null, 4); fse.outputFile('desired/path/to/metrics.json', content, function (err) { if (err) { console.error(err); } }); }); 

As a result, we get the text metrics of the necessary fonts:

 { "Arial": { "actualBoundingBoxAscent": 0, "actualBoundingBoxDescent": 24, "actualBoundingBoxLeft": 0, "actualBoundingBoxRight": 93, "alphabeticBaseline": 0, "emHeightAscent": 0, "emHeightDescent": 0, "fontBoundingBoxAscent": 22, "fontBoundingBoxDescent": 5, "hangingBaseline": 17.600000381469727, "ideographicBaseline": -5, "width": 93.375 }, "Karla Bold": { "actualBoundingBoxAscent": 0, "actualBoundingBoxDescent": 24, "actualBoundingBoxLeft": 0, "actualBoundingBoxRight": 85, "alphabeticBaseline": 0, "emHeightAscent": 0, "emHeightDescent": 0, "fontBoundingBoxAscent": 22, "fontBoundingBoxDescent": 6, "hangingBaseline": 17.600000381469727, "ideographicBaseline": -6, "width": 85.30078125 }, "Karla Regular": { "actualBoundingBoxAscent": 0, "actualBoundingBoxDescent": 24, "actualBoundingBoxLeft": 0, "actualBoundingBoxRight": 85, "alphabeticBaseline": 0, "emHeightAscent": 0, "emHeightDescent": 0, "fontBoundingBoxAscent": 22, "fontBoundingBoxDescent": 6, "hangingBaseline": 17.600000381469727, "ideographicBaseline": -6, "width": 85.30078125 } } 

In this example, textual metrics will be required only for Arial, “Karla Bold” and “Karla Regular” fonts, but in practice it can be any available system, custom, or cdn-delivered font in the quantity necessary to maintain all localizations of your project.

As a rule, the operation of obtaining text metrics is one-time and must be restarted only when the fonts used in the project are changed. For most cases, it is enough to generate the values ​​once, save them to a file and use them during assembly.

When using the font-metrics package, the process of generating text metrics is greatly simplified:

 import fontMetrics from 'font-metrics'; const fontParser = fontMetrics({ fonts: [{ fontFamily: 'Arial' }, { fontFamily: 'Karla Regular', src: '//fonts.gstatic.com/s/karla/v6/S1bXQ0LrY7AzefpgNae9sYDGDUGfDkXyfkzVDelzfFk.woff2' }, { fontFamily: 'Karla Bold', src: '//fonts.gstatic.com/s/karla/v6/r3NqIkFHFaF3esZDc3WT5BkAz4rYn47Zy2rvigWQf6w.woff2' }], output: './font-metrics', filename: 'font-metrics.json' }); fontParser.parse(); 

Result:

 { "metrics": { "Arial": { "_fontSize": 24, "_textBaseline": "alphabetic", "actualBoundingBoxAscent": 0, "actualBoundingBoxDescent": 24, "actualBoundingBoxLeft": 0, "actualBoundingBoxRight": 93, "alphabeticBaseline": 0, "emHeightAscent": 0, "emHeightDescent": 0, "fontBoundingBoxAscent": 22, "fontBoundingBoxDescent": 5, "hangingBaseline": 17.600000381469727, "ideographicBaseline": -5, "width": 93.375 }, "Karla Bold": { "_fontSize": 24, "_textBaseline": "alphabetic", "actualBoundingBoxAscent": 0, "actualBoundingBoxDescent": 24, "actualBoundingBoxLeft": 0, "actualBoundingBoxRight": 85, "alphabeticBaseline": 0, "emHeightAscent": 0, "emHeightDescent": 0, "fontBoundingBoxAscent": 22, "fontBoundingBoxDescent": 6, "hangingBaseline": 17.600000381469727, "ideographicBaseline": -6, "width": 85.30078125 }, "Karla Regular": { "_fontSize": 24, "_textBaseline": "alphabetic", "actualBoundingBoxAscent": 0, "actualBoundingBoxDescent": 24, "actualBoundingBoxLeft": 0, "actualBoundingBoxRight": 85, "alphabeticBaseline": 0, "emHeightAscent": 0, "emHeightDescent": 0, "fontBoundingBoxAscent": 22, "fontBoundingBoxDescent": 6, "hangingBaseline": 17.600000381469727, "ideographicBaseline": -6, "width": 85.30078125 } }, "src": [ { "fontFamily": "Arial" }, { "fontFamily": "Karla Regular", "src": "//fonts.gstatic.com/s/karla/v6/S1bXQ0LrY7AzefpgNae9sYDGDUGfDkXyfkzVDelzfFk.woff2" }, { "fontFamily": "Karla Bold", "src": "//fonts.gstatic.com/s/karla/v6/r3NqIkFHFaF3esZDc3WT5BkAz4rYn47Zy2rvigWQf6w.woff2" } ] } 

Postcss-text-indentation-adjustment plugin integration


The principle of operation of the postcss-text-indentation-adjustment plugin is based on the description of the initial value adjustments applied to the declaration (in the example in question it is 24px) indicating the typographic classes for which this value should be corrected. The description of the adjustment is performed as a comment inside the declaration value and allows you to safely embed the plugin in the project assembly.

Consider how adjustments can be described for our example:

 /* banner.scss */ @import 'path/to/typography.scss'; .banner { display: flex; flex-direction: column; justify-content: flex-end; background: url('path/to/banner-image.png') no-repeat center bottom; background-size: cover; &__content { color: #fff; padding: 48px 0 48px 48px /* {48px, .type-h2} 0 {48px, .type-p1} 48px */; &-title { @extend .type-h2; } &-description { @extend .type-p1; max-width: 80%; margin-top: 24px /* {24px, .type-h2, .type-p1} */; } &-links { @extend .type-p1; display: flex; flex-direction: row; margin-top: 24px /* {24px, .type-p1, .type-p1} */; li { margin-left: 18px; &:first-child { margin-left: 0; } a { color: inherit; } } } } } 

Processing adjustments


Import the necessary libraries.

 // node-sass       import nodeSass from 'node-sass'; // postcss     import postcss from 'postcss'; // fse  fs          import fse from 'fs-extra'; // path      import path from 'path'; // postcss-scss   postcss   scss   css import postcssSCSS from 'postcss-scss'; // postcss-text-indentation-adjustment    ,       import textIndentationAdjustment, {parser} from 'postcss-text-indentation-adjustment'; // postcss-partial-import    scss ,      import postcssPartialImport from 'postcss-partial-import'; // css-mqpacker   - (   ) import cssMqPacker from 'css-mqpacker'; // postcss-merge-rules   css      (   ) import mergeRules from 'postcss-merge-rules'; //  ,       import {metrics} from 'path/to/metrics.json'; //     scss  css     const typography = nodeSass.renderSync({ file: 'path/to/typography.scss' }).css.toString(); //  ,   ,       const typographyParser = parser({ metrics: metrics }); //        const parsedTypography = typographyParser.parse(typography); //  postcss ,       const typographyAdjustmentPlugin = textIndentationAdjustment({ corrections: parsedTypography, plainCSS: false //           (,   scss) }); //  postcss   scss fse.readFile('path/to/banner.scss', (err, scss) => { postcss([postcssPartialImport(), postcssTypographyAdjustmentPlugin]) .process(scss, { syntax: postcssSCSS, from: 'path/to/banner.scss', to: `path/to/banner.css` }) .then(postcssResult => { return new Promise((resolve, reject) => { nodeSass.render({ data: postcssResult.css, outputStyle: 'expanded' }, (err, result) => { resolve(result); }); }); }) .then(result => { //  -      return postcss([mergeRules(), cssMqPacker()]).process(result.css); }) .then(result => { fse.outputFile('path/to/banner.css', result.css); }) .catch(e => { console.log(e); }); }); 

As a result, a file containing the following rules will be compiled (typographical styles and the result of @extend are excluded to focus on the generated corrections) :

 .banner { display: flex; flex-direction: column; justify-content: flex-end; background: url("path/to/banner-image.png") no-repeat center bottom; background-size: cover; } .banner__content { color: #fff; padding: 39.5px 0 43px 48px; } .banner__content-description { max-width: 80%; margin-top: 10.5px; } html[lang^="de"] .banner__content-description { margin-top: 10.5px; } .banner__content-links { display: flex; flex-direction: row; margin-top: 14px; } .banner__content-links li { margin-left: 18px; } .banner__content-links li:first-child { margin-left: 0; } .banner__content-links li a { color: inherit; } html[lang^="de"] .banner__content-links { margin-top: 14px; } html[lang^="de"] .banner__content { padding: 39.5px 0 43px 48px; } @media only screen and (min-width: 480px) and (max-width: 767px) { .banner__content-description { margin-top: 8.5px; } html[lang^="de"] .banner__content-description { margin-top: 7.5px; } .banner__content-links { margin-top: 14px; } html[lang^="de"] .banner__content-links { margin-top: 14px; } .banner__content { padding: 37.5px 0 43px 48px; } html[lang^="de"] .banner__content { padding: 36.5px 0 43px 48px; } } @media only screen and (min-width: 768px) { .banner__content-description { margin-top: -0.5px; } html[lang^="de"] .banner__content-description { margin-top: -1.5px; } .banner__content-links { margin-top: 11px; } html[lang^="de"] .banner__content-links { margin-top: 11px; } .banner__content { padding: 30px 0 41.5px 48px; } html[lang^="de"] .banner__content { padding: 29px 0 41.5px 48px; } } 

Result for the English locale:







Result for the German locale:







As you can see, the result of the indentation rendering has been significantly adjusted.

Adjustment Syntax


(The compiled values ​​are additionally passed through the plugins of combining selectors and media queries - css-mqpacker, postcss-merge-rules)

1. Adjustments are made in the form of a comment and are located inside the declaration value .

 .rule-selector { padding-top: 24px /* */; } 

2. Each value that needs to be adjusted is framed in braces (corrective group).

 .rule-selector { padding-top: 24px /* {24px} */; } 

3. Typographic classes or tags, for which corrections should be applied, should be comma after the base value.

 .rule-selector { padding-top: 24px /* {24px, h3, .type-h2} */; } 

4. If it is necessary to specify several values, each of them is placed in its own corrective group, which will be replaced by the calculated value.

 .rule-selector { padding-top: 24px 0 24px /* {24px, h3, .type-h2} 0 {24px, .type-h2, .copy-p1} */; } 

5. The content of the commentary with the result of the calculation of all corrective groups is set by the plugin to the final value of the declaration.

 .rule-selector { padding-top: 17px 0 19px; } 

6. If there are parent selectors in the source file of typographic classes - an additional rule is created, which includes a combination of the parent and target selectors, as well as declarations with calculated values ​​for all combinations of typographic selectors.

 /* typography */ .p1 { font-size: 16px; line-height: 24px; font-family: Arial; .parent-selector-1 & { font-size: 18px; line-height: 26px; font-family: Arial; } } .p2 { font-size: 18px; line-height: 22px; font-family: Arial; .parent-selector-2 & { font-size: 14px; line-height: 20px; font-family: Arial; } } 

 /* input */ .rule-selector { padding-top: 24px /* {24px, .p1, .p2} */; } 

 /* output */ .rule-selector { padding-top: 13px; } .parent-selector-1 .rule-selector { padding-top: 12px; } .parent-selector-2 .rule-selector { padding-top: 13px; } 

7. If there are media queries or media queries in combination with parent selectors - all possible combinations for typographic selectors involved in the adjustment are created.

 /* typography */ .p1 { font-size: 16px; line-height: 24px; font-family: Arial; .parent-selector-1 & { font-size: 18px; line-height: 26px; font-family: Arial; } @media (min-width: 768px) { font-size: 22px; line-height: 28px; font-family: Arial; html[lang^="de"] .parent-selector-3 & { font-size: 28px; line-height: 40px; font-family: Arial; } } } .p2 { font-size: 18px; line-height: 22px; font-family: Arial; .parent-selector-2 & { font-size: 14px; line-height: 20px; font-family: Arial; } @media (min-width: 321px) { font-size: 22px; line-height: 28px; font-family: Arial; html[lang^="de"] .parent-selector-4 & { font-size: 28px; line-height: 40px; font-family: Arial; } } } 

 /* input */ .rule-selector { padding-top: 24px /* {24px, .p1, .p2} */; } 

 /* output */ .rule-selector { padding-top: 13px; } .parent-selector-1 .rule-selector { padding-top: 12px; } .parent-selector-2 .rule-selector { padding-top: 13px; } @media (min-width: 768px) { .rule-selector { padding-top: 13px; } html[lang^="de"] .parent-selector-3 .rule-selector { padding-top: 14px; } } @media (min-width: 321px) { .rule-selector { padding-top: 12px; } html[lang^="de"] .parent-selector-4 .rule-selector { padding-top: 14px; } } 

8. You can check the parameters used to calculate the final values ​​using the - debug flag

 /* input */ .rule-selector { padding-top: 24px /* {24px, .p1, .p2} --debug */; } 

As a result, the console will display some of the data used to create the correction.

Features of the use of current at the time of this writing version (1.0.9)



 const typographyAdjustmentPlugin = textIndentationAdjustment({ corrections: parsedTypography, plainCSS: false }); 

Finally



Thanks for attention. I will be glad to hear reasonable criticism, as well as suggestions for improvement and optimization.

Source: https://habr.com/ru/post/344984/


All Articles