{"id":89,"date":"2019-12-07T11:38:10","date_gmt":"2019-12-07T11:38:10","guid":{"rendered":"https:\/\/potatodie.nl\/diffuse-write-ups\/?p=89"},"modified":"2020-09-22T20:22:41","modified_gmt":"2020-09-22T20:22:41","slug":"transforming-a-static-element","status":"publish","type":"post","link":"https:\/\/potatodie.nl\/diffuse-write-ups\/transforming-a-static-element\/","title":{"rendered":"Transforming a static element"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">When a CSS transform is applied to an element, 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-css\">\n      CSS    <\/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-1001282916\" \n    id=\"codemirror-1001282916\"\n  >a {\n    display: inline-block;\n    transform: scale(2);\n}<\/textarea>\n  <script>\n    CodeMirror.fromTextArea( document.getElementById('codemirror-1001282916'), {\n      mode: 'css',\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\">it seems that element&#8217;s <code>position<\/code> property is forced to <code>relative<\/code>. This <em>side effect<\/em> introduces quirky behaviour, when you depend on the position being static.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Here&#8217;s an explanation of what happens. Luckily there&#8217;s also a simple solution to this problem.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">A child outgrown its parent<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Suppose we have an article element that contains a link:<\/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-1346900524\" \n    id=\"codemirror-1346900524\"\n  >&lt;article&gt;\n    &lt;p&gt;Some text&lt;\/p&gt;\n    &lt;a class=&quot;button&quot; href=&quot;link-to-somewhere&quot;&gt;Go&lt;\/a&gt;\n&lt;\/article&gt;<\/textarea>\n  <script>\n    CodeMirror.fromTextArea( document.getElementById('codemirror-1346900524'), {\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\">To expand the area of the link responding to hovering and clicking\/tapping to the whole article we can define a CSS pseudo-element:<\/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-css\">\n      CSS    <\/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-275584968\" \n    id=\"codemirror-275584968\"\n  >a::before {\n    content: &#039;&#039;;\n    position: absolute;\n    top: 0;\n    left: 0;\n    right: 0;\n    bottom: 0;\n}<\/textarea>\n  <script>\n    CodeMirror.fromTextArea( document.getElementById('codemirror-275584968'), {\n      mode: 'css',\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\">This pseudo-element behaves like a child element of the <code>&lt;a&gt;<\/code>-tag in the DOM. By positioning it <code>absolute <\/code>and setting <code>top, left, right<\/code> and <code>bottom <\/code>to 0, it takes up the space of its nearest ancestor that is a positioned element. We want that ancestor to be  our <code>&lt;article&gt;<\/code>. <\/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-css\">\n      CSS    <\/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-1406709361\" \n    id=\"codemirror-1406709361\"\n  >article {\n    position: relative;\n}<\/textarea>\n  <script>\n    CodeMirror.fromTextArea( document.getElementById('codemirror-1406709361'), {\n      mode: 'css',\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\">Events received by the large pseudo-element now bubble up to its small parent. Below is an example that shows a box without and with mouseover.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"733\" height=\"496\" src=\"https:\/\/potatodie.nl\/diffuse-write-ups\/wp-content\/uploads\/2019\/12\/Nieuwsbrief-kaart-met-zonder-Hover.png\" alt=\"\" class=\"wp-image-112\" srcset=\"https:\/\/potatodie.nl\/diffuse-write-ups\/wp-content\/uploads\/2019\/12\/Nieuwsbrief-kaart-met-zonder-Hover.png 733w, https:\/\/potatodie.nl\/diffuse-write-ups\/wp-content\/uploads\/2019\/12\/Nieuwsbrief-kaart-met-zonder-Hover-300x203.png 300w\" sizes=\"auto, (max-width: 733px) 100vw, 733px\" \/><figcaption>The right image shows hovering works on the whole article. In this case the pseudo-element shows itself as a semi-transparent overlay.<\/figcaption><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Check that this works on <a href=\"https:\/\/codepen.io\/potatoDie\/pen\/JjoYLqW\">CodePen<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Scaling up<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Now suppose we styled the anchor element as a button and we want to react on hovering over the article by making the button bigger. <\/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-css\">\n      CSS    <\/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-1838704439\" \n    id=\"codemirror-1838704439\"\n  >a:hover {\n    transform: scale(1.2);\n}<\/textarea>\n  <script>\n    CodeMirror.fromTextArea( document.getElementById('codemirror-1838704439'), {\n      mode: 'css',\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\">Can you predict what will happen? Check this <a href=\"https:\/\/codepen.io\/potatoDie\/pen\/jOEbzoj\">CodePen<\/a>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">It turns out that if you hover over the article but not the anchor the button starts to flicker. What happens is that when a transform is applied, the transformation must be relative to some basic state. Therefor its position is secretly changed to <code>relative<\/code>. Now the pseudo-element that was positioned relative to the article is suddenly positioned relative to the button. In effect the pseudo-element shrinks to the size of the button. This ends the hovering and as a consequence the transform and the <code>position<\/code> property of the button reverts to <code>static<\/code>. And then everything starts over again.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Side effects<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">So when a transform is applied to a static  element, its position property is changed as a side effect. And as happens more often, side effects cause bugs, or quirky behaviour.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">To prevent this I guess transformable objects should be explicitly positioned elements. However, this restriction is not in the <a href=\"https:\/\/www.w3.org\/TR\/css-transforms-1\/#terminology\">W3 specification<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Solution<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">There is a simple solution to this problem. We need to change the HTML structure a bit and place the button inside the anchor element, as a child element:<\/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-1535037863\" \n    id=\"codemirror-1535037863\"\n  >&lt;article&gt;\n    &lt;p&gt;Some text&lt;\/p&gt;\n    &lt;a href=&quot;link-to-somewhere&quot;&gt;\n        &lt;div class=&quot;button&quot;&gt;Go&lt;\/div&gt;\n    &lt;\/a&gt;\n&lt;\/article&gt;<\/textarea>\n  <script>\n    CodeMirror.fromTextArea( document.getElementById('codemirror-1535037863'), {\n      mode: 'xml',\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\">Apply the transform to the button when the anchor, which is now the parent of the button, is hovered. This leaves the <code>position <\/code>property of the anchor alone, and prevents the pseudo-element of the anchor to shrink.<\/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-css\">\n      CSS    <\/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-612537380\" \n    id=\"codemirror-612537380\"\n  >a:hover .button {\n  transform: scale(1.5);\n}<\/textarea>\n  <script>\n    CodeMirror.fromTextArea( document.getElementById('codemirror-612537380'), {\n      mode: 'css',\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<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"362\" height=\"479\" src=\"https:\/\/potatodie.nl\/diffuse-write-ups\/wp-content\/uploads\/2019\/12\/Nieuwsbrief-kaaart-met-hover-en-scale.png\" alt=\"\" class=\"wp-image-114\" srcset=\"https:\/\/potatodie.nl\/diffuse-write-ups\/wp-content\/uploads\/2019\/12\/Nieuwsbrief-kaaart-met-hover-en-scale.png 362w, https:\/\/potatodie.nl\/diffuse-write-ups\/wp-content\/uploads\/2019\/12\/Nieuwsbrief-kaaart-met-hover-en-scale-227x300.png 227w\" sizes=\"auto, (max-width: 362px) 100vw, 362px\" \/><figcaption>Scaled button on hovering the article.<\/figcaption><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Here&#8217;s a final <a href=\"https:\/\/codepen.io\/potatoDie\/pen\/abzvGxG\">CodePen<\/a> to see this soluton at work.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>When a CSS transform is applied to an element, that element&#8217;s position property is forced to relative. This side effect introduces quirky behaviour, when you depend on the position being static.<\/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":[13,14,12],"class_list":["post-89","post","type-post","status-publish","format-standard","hentry","category-css","category-web-development","tag-pseudo-element","tag-side-effect","tag-transform"],"acf":[],"_links":{"self":[{"href":"https:\/\/potatodie.nl\/diffuse-write-ups\/wp-json\/wp\/v2\/posts\/89","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=89"}],"version-history":[{"count":22,"href":"https:\/\/potatodie.nl\/diffuse-write-ups\/wp-json\/wp\/v2\/posts\/89\/revisions"}],"predecessor-version":[{"id":764,"href":"https:\/\/potatodie.nl\/diffuse-write-ups\/wp-json\/wp\/v2\/posts\/89\/revisions\/764"}],"wp:attachment":[{"href":"https:\/\/potatodie.nl\/diffuse-write-ups\/wp-json\/wp\/v2\/media?parent=89"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/potatodie.nl\/diffuse-write-ups\/wp-json\/wp\/v2\/categories?post=89"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/potatodie.nl\/diffuse-write-ups\/wp-json\/wp\/v2\/tags?post=89"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}