{"id":130,"date":"2019-12-19T12:15:04","date_gmt":"2019-12-19T12:15:04","guid":{"rendered":"https:\/\/potatodie.nl\/diffuse-write-ups\/?p=130"},"modified":"2019-12-20T15:12:51","modified_gmt":"2019-12-20T15:12:51","slug":"scaling-a-tile-with-text","status":"publish","type":"post","link":"https:\/\/potatodie.nl\/diffuse-write-ups\/scaling-a-tile-with-text\/","title":{"rendered":"Scaling grid tiles containing text"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">Suppose we have a design with a component that contains an image and text, with responsive dimensions and a fixed height to width ratio. The font size scales too, so the text wraps the same for each width.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"573\" src=\"https:\/\/potatodie.nl\/diffuse-write-ups\/wp-content\/uploads\/2019\/12\/tile-proportional-e1576838576328-1024x573.png\" alt=\"\" class=\"wp-image-139\" srcset=\"https:\/\/potatodie.nl\/diffuse-write-ups\/wp-content\/uploads\/2019\/12\/tile-proportional-e1576838576328-1024x573.png 1024w, https:\/\/potatodie.nl\/diffuse-write-ups\/wp-content\/uploads\/2019\/12\/tile-proportional-e1576838576328-300x168.png 300w, https:\/\/potatodie.nl\/diffuse-write-ups\/wp-content\/uploads\/2019\/12\/tile-proportional-e1576838576328-768x430.png 768w, https:\/\/potatodie.nl\/diffuse-write-ups\/wp-content\/uploads\/2019\/12\/tile-proportional-e1576838576328-1536x859.png 1536w, https:\/\/potatodie.nl\/diffuse-write-ups\/wp-content\/uploads\/2019\/12\/tile-proportional-e1576838576328-1200x671.png 1200w, https:\/\/potatodie.nl\/diffuse-write-ups\/wp-content\/uploads\/2019\/12\/tile-proportional-e1576838576328.png 1814w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption> Proportionally scaled tile. <\/figcaption><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">This is what the HTML structure of the component might look like:<\/p>\n\n\n<div class=\"wp-block-advanced-gutenberg-blocks-code\">\n  <header class=\"wp-block-advanced-gutenberg-blocks-code__header\">\n    <div class=\"wp-block-advanced-gutenberg-blocks-code__lang is-lang-html\">\n      HTML    <\/div>\n    <div class=\"wp-block-advanced-gutenberg-blocks-code__file\">\n          <\/div>\n  <\/header>\n  <textarea \n    class=\"wp-block-advanced-gutenberg-blocks-code__source\" \n    name=\"codemirror-56119813\" \n    id=\"codemirror-56119813\"\n  >&lt;article class=&quot;tile&quot;&gt;\n    &lt;figure&gt;\n        &lt;img src=&quot;&quot; alt=&quot;&quot; \/&gt;\n    &lt;\/figure&gt;\n    &lt;h2&gt;&lt;\/h2&gt;\n    &lt;p&gt;&lt;\/p&gt;\n&lt;\/article&gt;      <\/textarea>\n  <script>\n    CodeMirror.fromTextArea( document.getElementById('codemirror-56119813'), {\n      mode: 'xml',\n      readOnly: true,\n      theme: 'hopscotch', \n      lineNumbers: true,\n      firstLineNumber: 1,\n      matchBrackets: true,\n      indentUnit: 4,\n      tabSize: 4,\n      lineWrapping: true,\n    } ); \n  <\/script>\n<\/div>\n\n\n\n<p class=\"wp-block-paragraph\">The height of the tile and the font size are proportional to the tile width. How can we calculate them?<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">What is the width of the tile?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Suppose the tiles are arranged in three columns in a grid that takes up 80% of the viewport width, leaving a 10% margin on each side.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"1006\" src=\"https:\/\/potatodie.nl\/diffuse-write-ups\/wp-content\/uploads\/2019\/12\/3kol-1024x1006.jpg\" alt=\"\" class=\"wp-image-143\" srcset=\"https:\/\/potatodie.nl\/diffuse-write-ups\/wp-content\/uploads\/2019\/12\/3kol-1024x1006.jpg 1024w, https:\/\/potatodie.nl\/diffuse-write-ups\/wp-content\/uploads\/2019\/12\/3kol-300x295.jpg 300w, https:\/\/potatodie.nl\/diffuse-write-ups\/wp-content\/uploads\/2019\/12\/3kol-768x754.jpg 768w, https:\/\/potatodie.nl\/diffuse-write-ups\/wp-content\/uploads\/2019\/12\/3kol-1200x1178.jpg 1200w, https:\/\/potatodie.nl\/diffuse-write-ups\/wp-content\/uploads\/2019\/12\/3kol.jpg 1444w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption>Desktop layout. Three columns take up 80% of the viewport width.<\/figcaption><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Then the width of a tile can be expressed in viewport width and gutter width:<\/p>\n\n\n<div class=\"wp-block-advanced-gutenberg-blocks-code\">\n  <header class=\"wp-block-advanced-gutenberg-blocks-code__header\">\n    <div class=\"wp-block-advanced-gutenberg-blocks-code__lang is-lang-sass\">\n      Sass    <\/div>\n    <div class=\"wp-block-advanced-gutenberg-blocks-code__file\">\n          <\/div>\n  <\/header>\n  <textarea \n    class=\"wp-block-advanced-gutenberg-blocks-code__source\" \n    name=\"codemirror-845450835\" \n    id=\"codemirror-845450835\"\n  >$grid-gutter-width: 30px;\n$tile-width: calc(80vw \/ 3 - #{$grid-gutter-width});<\/textarea>\n  <script>\n    CodeMirror.fromTextArea( document.getElementById('codemirror-845450835'), {\n      mode: 'sass',\n      readOnly: true,\n      theme: 'hopscotch', \n      lineNumbers: false,\n      firstLineNumber: 1,\n      matchBrackets: true,\n      indentUnit: 4,\n      tabSize: 4,\n      lineWrapping: true,\n    } ); \n  <\/script>\n<\/div>\n\n\n\n<p class=\"wp-block-paragraph\">We could use <code>$tile-width<\/code> to express the height and position of the tile and its parts, like this:<\/p>\n\n\n<div class=\"wp-block-advanced-gutenberg-blocks-code\">\n  <header class=\"wp-block-advanced-gutenberg-blocks-code__header\">\n    <div class=\"wp-block-advanced-gutenberg-blocks-code__lang is-lang-sass\">\n      Sass    <\/div>\n    <div class=\"wp-block-advanced-gutenberg-blocks-code__file\">\n          <\/div>\n  <\/header>\n  <textarea \n    class=\"wp-block-advanced-gutenberg-blocks-code__source\" \n    name=\"codemirror-485133232\" \n    id=\"codemirror-485133232\"\n  >.tile {\n\theight: calc(1.25 * #{$tile-width});\n\tpadding-top: calc(0.8 * #{$tile-width});\n\n\tfigure {\n        max-height: calc(.75 * #{$tile-width});\n\t}\n}<\/textarea>\n  <script>\n    CodeMirror.fromTextArea( document.getElementById('codemirror-485133232'), {\n      mode: 'sass',\n      readOnly: true,\n      theme: 'hopscotch', \n      lineNumbers: false,\n      firstLineNumber: 1,\n      matchBrackets: true,\n      indentUnit: 4,\n      tabSize: 4,\n      lineWrapping: true,\n    } ); \n  <\/script>\n<\/div>\n\n\n\n<p class=\"wp-block-paragraph\">But <code>$tile-width<\/code> will likely vary for different layouts\/media queries.  You can&#8217;t use Sass variables outside of the media query that it is defined in. So you would have to set the <code>height<\/code>, <code>padding-top<\/code> and <code>max-height<\/code> properties for every media query. <\/p>\n\n\n\n<p class=\"wp-block-paragraph\">I would like to use the CSS property <code>font-size<\/code> to carry the result of our calculations and then set the sizes in <code>em<\/code> units. So let&#8217;s first calculate the font size.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Determine font size<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The font size is proportional to the tile width, or in other words <code>font-size<\/code> equals <code>$tile-width<\/code> multiplied with a constant, <code>$font-size-factor<\/code>. If we decide that for e.g. a viewport width of 1500px we want a font size of 18px , using the above expression for <code>$tile-width<\/code> we find <code>370px * $font-size-factor = 18px<\/code>, from which  <code>$font-size-factor<\/code> can be calculated.<\/p>\n\n\n<div class=\"wp-block-advanced-gutenberg-blocks-code\">\n  <header class=\"wp-block-advanced-gutenberg-blocks-code__header\">\n    <div class=\"wp-block-advanced-gutenberg-blocks-code__lang is-lang-sass\">\n      Sass    <\/div>\n    <div class=\"wp-block-advanced-gutenberg-blocks-code__file\">\n          <\/div>\n  <\/header>\n  <textarea \n    class=\"wp-block-advanced-gutenberg-blocks-code__source\" \n    name=\"codemirror-2027921110\" \n    id=\"codemirror-2027921110\"\n  >$font-size-factor: 18px \/ (400px - $grid-gutter-width);<\/textarea>\n  <script>\n    CodeMirror.fromTextArea( document.getElementById('codemirror-2027921110'), {\n      mode: 'sass',\n      readOnly: true,\n      theme: 'hopscotch', \n      lineNumbers: true,\n      firstLineNumber: 1,\n      matchBrackets: true,\n      indentUnit: 4,\n      tabSize: 4,\n      lineWrapping: true,\n    } ); \n  <\/script>\n<\/div>\n\n\n\n<p class=\"wp-block-paragraph\">That gives us font-size too:<\/p>\n\n\n<div class=\"wp-block-advanced-gutenberg-blocks-code\">\n  <header class=\"wp-block-advanced-gutenberg-blocks-code__header\">\n    <div class=\"wp-block-advanced-gutenberg-blocks-code__lang is-lang-sass\">\n      Sass    <\/div>\n    <div class=\"wp-block-advanced-gutenberg-blocks-code__file\">\n          <\/div>\n  <\/header>\n  <textarea \n    class=\"wp-block-advanced-gutenberg-blocks-code__source\" \n    name=\"codemirror-1268985291\" \n    id=\"codemirror-1268985291\"\n  >font-size: calc(#{$tile-width} * #{$font-size-factor});<\/textarea>\n  <script>\n    CodeMirror.fromTextArea( document.getElementById('codemirror-1268985291'), {\n      mode: 'sass',\n      readOnly: true,\n      theme: 'hopscotch', \n      lineNumbers: true,\n      firstLineNumber: 1,\n      matchBrackets: true,\n      indentUnit: 4,\n      tabSize: 4,\n      lineWrapping: true,\n    } ); \n  <\/script>\n<\/div>\n\n\n\n<h3 class=\"wp-block-heading\">Express tile width relative to font size<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Unlike <code>$tile-width <\/code>we can use the CSS property <code>font-size<\/code> outside of the media query that defines it. Or at least we can refer to its value: 1em. Since <code>font-size = $tile-width * $font-size-factor<\/code> we can express the tile width in ems too, as:<\/p>\n\n\n<div class=\"wp-block-advanced-gutenberg-blocks-code\">\n  <header class=\"wp-block-advanced-gutenberg-blocks-code__header\">\n    <div class=\"wp-block-advanced-gutenberg-blocks-code__lang is-lang-sass\">\n      Sass    <\/div>\n    <div class=\"wp-block-advanced-gutenberg-blocks-code__file\">\n          <\/div>\n  <\/header>\n  <textarea \n    class=\"wp-block-advanced-gutenberg-blocks-code__source\" \n    name=\"codemirror-1425597818\" \n    id=\"codemirror-1425597818\"\n  >$width-in-ems: 1em \/ #{$font-size-factor};<\/textarea>\n  <script>\n    CodeMirror.fromTextArea( document.getElementById('codemirror-1425597818'), {\n      mode: 'sass',\n      readOnly: true,\n      theme: 'hopscotch', \n      lineNumbers: true,\n      firstLineNumber: 1,\n      matchBrackets: true,\n      indentUnit: 4,\n      tabSize: 4,\n      lineWrapping: true,\n    } ); \n  <\/script>\n<\/div>\n\n\n\n<p class=\"wp-block-paragraph\">That is weird. We calculated font-size based on tile width, and then calculate tile width based on font-size. But in the process we changed from pixel units to ems, and we use 1em as a variable, independent of which media query applies. We now have a constant expression for tile width.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Now we can set the heights of the tile and its parts as follows:<\/p>\n\n\n<div class=\"wp-block-advanced-gutenberg-blocks-code\">\n  <header class=\"wp-block-advanced-gutenberg-blocks-code__header\">\n    <div class=\"wp-block-advanced-gutenberg-blocks-code__lang is-lang-sass\">\n      Sass    <\/div>\n    <div class=\"wp-block-advanced-gutenberg-blocks-code__file\">\n          <\/div>\n  <\/header>\n  <textarea \n    class=\"wp-block-advanced-gutenberg-blocks-code__source\" \n    name=\"codemirror-1716251293\" \n    id=\"codemirror-1716251293\"\n  >.tile {\n\theight: calc(1.5  * #{$width-in-ems});\n\tpadding-top: calc(0.8 * #{$width-in-ems});\n\n\tfigure {\n        max-height: calc(0.75  * #{$width-in-ems});\n\t}\n}<\/textarea>\n  <script>\n    CodeMirror.fromTextArea( document.getElementById('codemirror-1716251293'), {\n      mode: 'sass',\n      readOnly: true,\n      theme: 'hopscotch', \n      lineNumbers: false,\n      firstLineNumber: 1,\n      matchBrackets: true,\n      indentUnit: 4,\n      tabSize: 4,\n      lineWrapping: true,\n    } ); \n  <\/script>\n<\/div>\n\n\n\n<h2 class=\"wp-block-heading\">Other layouts<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">If the viewport is too small, the tiles will stack.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"910\" src=\"https:\/\/potatodie.nl\/diffuse-write-ups\/wp-content\/uploads\/2019\/12\/2kol80-10-1024x910.jpg\" alt=\"\" class=\"wp-image-145\" srcset=\"https:\/\/potatodie.nl\/diffuse-write-ups\/wp-content\/uploads\/2019\/12\/2kol80-10-1024x910.jpg 1024w, https:\/\/potatodie.nl\/diffuse-write-ups\/wp-content\/uploads\/2019\/12\/2kol80-10-300x267.jpg 300w, https:\/\/potatodie.nl\/diffuse-write-ups\/wp-content\/uploads\/2019\/12\/2kol80-10-768x682.jpg 768w, https:\/\/potatodie.nl\/diffuse-write-ups\/wp-content\/uploads\/2019\/12\/2kol80-10-1200x1066.jpg 1200w, https:\/\/potatodie.nl\/diffuse-write-ups\/wp-content\/uploads\/2019\/12\/2kol80-10.jpg 1336w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption>Tablet layout. Two columns take up 80% of the viewport width.<\/figcaption><\/figure>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"1016\" src=\"https:\/\/potatodie.nl\/diffuse-write-ups\/wp-content\/uploads\/2019\/12\/2kolm-1024x1016.jpg\" alt=\"Mobile layout. Two columns take up all viewport width minus fixed margin.\" class=\"wp-image-146\" srcset=\"https:\/\/potatodie.nl\/diffuse-write-ups\/wp-content\/uploads\/2019\/12\/2kolm-1024x1016.jpg 1024w, https:\/\/potatodie.nl\/diffuse-write-ups\/wp-content\/uploads\/2019\/12\/2kolm-300x298.jpg 300w, https:\/\/potatodie.nl\/diffuse-write-ups\/wp-content\/uploads\/2019\/12\/2kolm-150x150.jpg 150w, https:\/\/potatodie.nl\/diffuse-write-ups\/wp-content\/uploads\/2019\/12\/2kolm-768x762.jpg 768w, https:\/\/potatodie.nl\/diffuse-write-ups\/wp-content\/uploads\/2019\/12\/2kolm-1200x1190.jpg 1200w, https:\/\/potatodie.nl\/diffuse-write-ups\/wp-content\/uploads\/2019\/12\/2kolm.jpg 1255w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption>Mobile layout. Two columns take up all viewport width minus fixed margin.<\/figcaption><\/figure>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"882\" height=\"1024\" src=\"https:\/\/potatodie.nl\/diffuse-write-ups\/wp-content\/uploads\/2019\/12\/1kol-882x1024.jpg\" alt=\"\" class=\"wp-image-144\" srcset=\"https:\/\/potatodie.nl\/diffuse-write-ups\/wp-content\/uploads\/2019\/12\/1kol-882x1024.jpg 882w, https:\/\/potatodie.nl\/diffuse-write-ups\/wp-content\/uploads\/2019\/12\/1kol-259x300.jpg 259w, https:\/\/potatodie.nl\/diffuse-write-ups\/wp-content\/uploads\/2019\/12\/1kol-768x891.jpg 768w, https:\/\/potatodie.nl\/diffuse-write-ups\/wp-content\/uploads\/2019\/12\/1kol.jpg 1196w\" sizes=\"auto, (max-width: 882px) 100vw, 882px\" \/><figcaption>Small device layout. Single column.<\/figcaption><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">The calculation of <code>font-size<\/code> for the various layouts is as follows: <\/p>\n\n\n<div class=\"wp-block-advanced-gutenberg-blocks-code\">\n  <header class=\"wp-block-advanced-gutenberg-blocks-code__header\">\n    <div class=\"wp-block-advanced-gutenberg-blocks-code__lang is-lang-sass\">\n      Sass    <\/div>\n    <div class=\"wp-block-advanced-gutenberg-blocks-code__file\">\n          <\/div>\n  <\/header>\n  <textarea \n    class=\"wp-block-advanced-gutenberg-blocks-code__source\" \n    name=\"codemirror-1480018082\" \n    id=\"codemirror-1480018082\"\n  >   \/\/ 1 column\n$tile-width: calc(100vw - #{$grid-gutter-width} - 2 * #{$m});\nfont-size: calc(#{$tile-width} * #{$font-size-factor});\n\n@include media(mobile) {\n    \/\/ 2 columns\n    $tile-width: calc((50vw - #{$grid-gutter-width}) - #{$m});\n    font-size: calc(#{$tile-width} * #{$font-size-factor});\n}\n\n@include media(tablet) {\n    \/\/ 2 columns, more margin\n    $tile-width: calc((80vw - 2 * #{$grid-gutter-width}) \/ 2);\n    font-size: calc(#{$tile-width} * #{$font-size-factor});\n}\n\n@include media(desktop) {\n    \/\/ 3 columns\n    $tile-width: calc(80vw \/ 3 - #{$grid-gutter-width});\n    font-size: calc(#{$tile-width} * #{$font-size-factor});\n}\n\n@include media(wide) {\n    \/\/ 3 columns, but the width of the container is limited\n    font-size: 1em;\n}<\/textarea>\n  <script>\n    CodeMirror.fromTextArea( document.getElementById('codemirror-1480018082'), {\n      mode: 'sass',\n      readOnly: true,\n      theme: 'hopscotch', \n      lineNumbers: false,\n      firstLineNumber: 1,\n      matchBrackets: true,\n      indentUnit: 4,\n      tabSize: 4,\n      lineWrapping: false,\n    } ); \n  <\/script>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>Suppose we have a design with a component that contains an image and text, with responsive dimensions and a fixed height to width ratio. The font size scales too, so the text wraps the same for each width. This is what the HTML structure of the component might look like: The height of the tile [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[8,7],"tags":[18,17,16],"class_list":["post-130","post","type-post","status-publish","format-standard","hentry","category-css","category-web-development","tag-grid","tag-responsive-design","tag-sass"],"acf":[],"_links":{"self":[{"href":"https:\/\/potatodie.nl\/diffuse-write-ups\/wp-json\/wp\/v2\/posts\/130","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/potatodie.nl\/diffuse-write-ups\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/potatodie.nl\/diffuse-write-ups\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/potatodie.nl\/diffuse-write-ups\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/potatodie.nl\/diffuse-write-ups\/wp-json\/wp\/v2\/comments?post=130"}],"version-history":[{"count":9,"href":"https:\/\/potatodie.nl\/diffuse-write-ups\/wp-json\/wp\/v2\/posts\/130\/revisions"}],"predecessor-version":[{"id":151,"href":"https:\/\/potatodie.nl\/diffuse-write-ups\/wp-json\/wp\/v2\/posts\/130\/revisions\/151"}],"wp:attachment":[{"href":"https:\/\/potatodie.nl\/diffuse-write-ups\/wp-json\/wp\/v2\/media?parent=130"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/potatodie.nl\/diffuse-write-ups\/wp-json\/wp\/v2\/categories?post=130"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/potatodie.nl\/diffuse-write-ups\/wp-json\/wp\/v2\/tags?post=130"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}