{"id":7692,"date":"2020-11-26T23:09:41","date_gmt":"2020-11-26T22:09:41","guid":{"rendered":"https:\/\/www.creativejuiz.fr\/blog?p=7692"},"modified":"2020-11-26T23:09:41","modified_gmt":"2020-11-26T22:09:41","slug":"css-custom-properties-introduction-css-variables","status":"publish","type":"post","link":"https:\/\/www.creativejuiz.fr\/blog\/en\/css3\/css-custom-properties-introduction-css-variables","title":{"rendered":"CSS Custom Properties: introduction on CSS variables"},"content":{"rendered":"<p>Some years ago (2018 I think), I gave a talk during the <a href=\"https:\/\/www.meetup.com\/fr-FR\/luxembourgjs\/\">JavaScript Meetup of Luxembourg<\/a> where I presented briefly my interest for this new topic: CSS Variables. The official name of this specification is CSS Custom Properties. It allows you to store dynamic custom values to be used as CSS value within your code.<\/p>\n<p><!--more--><\/p>\n<p>Long time I should have publish this, but better late than never, isn&#8217;t it?<br \/>\nUnfortunately, the event wasn&#8217;t recorded, so here are the slides of the talk. But I&#8217;ll explain a bit more some of the concept of CSS Variables afterwards.<\/p>\n<p><script async class=\"speakerdeck-embed\" data-id=\"f45bda66736c413090ea308b1cd63f8f\" data-ratio=\"1.77777777777778\" src=\"\/\/speakerdeck.com\/assets\/embed.js\"><\/script><\/p>\n<p>I won&#8217;t go into detail of each slide, but don&#8217;t hesitate to ask me on <a href=\"https:\/\/twitter.com\/geoffreycrofte\">Twitter<\/a> if you have any question. You can even ask me to talk for your meetup or conference if you think this topic is interesting for your public.<\/p>\n<h2>CSS Variable: declaration and usage<\/h2>\n<p>So, first, how to use CSS Variables in your code?<\/p>\n<ol>\n<li>Declare your variable so they are available in a specific scope:<br \/>\n<div class=\"code-embed-wrapper\"> <pre class=\"language-css code-embed-pre line-numbers\"  data-start=\"1\" data-line-offset=\"0\"><code class=\"language-css code-embed-code\">:root {<br\/>    --colorprimary: #BADA33;<br\/>}<\/code><\/pre> <div class=\"code-embed-infos\"> <span class=\"code-embed-name\">Scope is global thanks to :root<\/span> <\/div> <\/div><\/li>\n<li>Then use the function <code>var()<\/code> to use the variable value as property value.<br \/>\n<div class=\"code-embed-wrapper\"> <pre class=\"language-css code-embed-pre line-numbers\"  data-start=\"1\" data-line-offset=\"0\"><code class=\"language-css code-embed-code\">a {<br\/>    color: var(--primarycolor);<br\/>}<\/code><\/pre> <div class=\"code-embed-infos\"> <\/div> <\/div><\/li>\n<li>The end.<\/li>\n<\/ol>\n<p>Note that variables are scoped. Meaning that if you declare your variables within a specific <code>div<\/code> for instance, the variable will be available only for this <code>div<\/code> and all its children.<\/p>\n<p>This is interesting because it allows you to create themable sections or contexts within your interface.<\/p>\n<h2>Why should I use CSS Variables?<\/h2>\n<p>Don&#8217;t feel the need to use it just because it&#8217;s trendy, use it if you need to make things vary here and there. For instance, it can be really handy for dark mode adjustments or media queries.<\/p>\n<div class=\"code-embed-wrapper\"> <pre class=\"language-css code-embed-pre line-numbers\"  data-line=\"29-35\" data-start=\"1\" data-line-offset=\"0\"><code class=\"language-css code-embed-code\">:root {<br\/>    --primarycolor: #BADA33;<br\/>    --pagebg: #FFF;<br\/>    --text: #444;<br\/>    --btn_bg: var(--primarycolor);<br\/>    --btn_text: black;<br\/>}<br\/><br\/>body {<br\/>    background: var(--pagebg);<br\/>    color: var(--text);<br\/>    line-height: 1.55;<br\/>}<br\/><br\/>a {<br\/>    color: var(--primarycolor);<br\/>}<br\/><br\/>button,<br\/>[type=&quot;submit&quot;],<br\/>[role=&quot;button&quot;] {<br\/>    border: 0;<br\/>    padding: 8px 16px;<br\/>    background: var(--btn_bg);<br\/>    color: var(--btn_text);<br\/>    border-radius: 4px;<br\/>}<br\/><br\/>@media (prefers-color-scheme: dark) {<br\/>    --primarycolor: #98B32A;<br\/>    --pagebg: #444;<br\/>    --text: #F2F2F2;<br\/>    --btn_bg: var(--primarycolor);<br\/>    --btn_text: white;<br\/>}<\/code><\/pre> <div class=\"code-embed-infos\"> <\/div> <\/div>\n<p>But, for a lesser need, you can also use it to vary styles while hovering or in active states of elements.<\/p>\n<div class=\"code-embed-wrapper\"> <pre class=\"language-css code-embed-pre line-numbers\"  data-line=\"12-16\" data-start=\"1\" data-line-offset=\"0\"><code class=\"language-css code-embed-code\">button {<br\/>    --icon_pos: 0;<br\/>    --bg_color: salmon;<br\/><br\/>    background: var(--bg_color);<br\/>}<br\/><br\/>button .icon {<br\/>    transform: translateX(var(--icon_pos));<br\/>}<br\/><br\/>button:hover,<br\/>button:focus {<br\/>    --bg_color: darksalmon;<br\/>    --icon_pos: 5px;<br\/>}<\/code><\/pre> <div class=\"code-embed-infos\"> <\/div> <\/div>\n<p>This code example is a bit too simple to find an interest into CSS Variable, but when you build complex component, you are happy to be able to set variables and vary those variables at the component level, without re-declaring all the selectors and states.<\/p>\n<h2>CSS Variables are live and JS-friendly<\/h2>\n<p>CSS Variables aren&#8217;t Sass or LESS variables, they are interpreted by the browser and live all the time. You can change it with JS if you need, or via usual class or states (<code>:hover<\/code>, <code>:active<\/code>, <code>:focus<\/code>, <code>:checked<\/code>, <code>:valid<\/code>, etc.) changing.<\/p>\n<p>For instance, this CodePen shows you JavaScript and CSS Variables working together.<\/p>\n<p class='codepen'  data-height='513' data-theme-id='0' data-slug-hash='VXKYvm' data-default-tab='result' data-animations='run' data-editable='' data-embed-version='2'>\n<\/p>\n\n<p>The JS part is quit short compared to the CSS linear-gradient declaration. For the JS Part we only set one variable depending on the cursor position.<\/p>\n<div class=\"code-embed-wrapper\"> <pre class=\"language-javascript code-embed-pre line-numbers\"  data-start=\"1\" data-line-offset=\"0\"><code class=\"language-javascript code-embed-code\">document.querySelector(&#039;.title&#039;).addEventListener(&#039;mousemove&#039;, (e) =&gt; {<br\/><br\/>  const x = e.pageX - e.target.offsetLeft<br\/><br\/>  e.target.style.setProperty(&#039;--x&#039;, `${ x }`)<br\/> <br\/>});<\/code><\/pre> <div class=\"code-embed-infos\"> <\/div> <\/div>\n<p>Then we use this variable in CSS to make things dynamic and animated.<\/p>\n<div class=\"code-embed-wrapper\"> <pre class=\"language-css code-embed-pre line-numbers\"  data-line=\"8\" data-start=\"1\" data-line-offset=\"0\"><code class=\"language-css code-embed-code\">.title {<br\/>    --x: 100;<br\/>    display: inline-block;<br\/>    margin: 0;<br\/>    font-size: 4rem;<br\/>    font-weight: 600;<br\/>    background-image: linear-gradient(45deg,#fff070 0%,#fff070 35%,#00c9d3 66%,#00c9d3 100%);<br\/>    background-image: linear-gradient(45deg,#fff070 0%,#fff070 calc(var(--x) * .1 * 1%),#00c9d3 calc(var(--x) * .4 * 1%),#00c9d3 calc(var(--x) * .7 * 1%) );<br\/>    -webkit-text-fill-color: transparent;<br\/>    -webkit-background-clip: text;<br\/>}<\/code><\/pre> <div class=\"code-embed-infos\"> <\/div> <\/div>\n<p>The double background declaration is for browser that doesn&#8217;t support CSS Vars. You can also use <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/CSS\/@supports\">@support<\/a> in some cases. Note that here the initial value is set directly in CSS at the beginning of the selector, scoped.<\/p>\n<p>Another similar shot just to share the effect with you. The first item shows you how it works when Variables are supported, and the 2 others in case they are not.<\/p>\n<p class='codepen'  data-height='380' data-theme-id='0' data-slug-hash='LdKxdj' data-default-tab='result' data-animations='run' data-editable='' data-embed-version='2'>\n<\/p>\n\n<h2>CSS Variables specificity<\/h2>\n<p>There are some things you need to now before jumping into using it without caution.<\/p>\n<ul>\n<li>CSS Variable names are case sensitive: <code>--button<\/code> and <code>--Button<\/code> are different variables.<\/li>\n<li>You can&#8217;t &#8220;cycle&#8221; variables. So you <strong>can&#8217;t<\/strong> write <code>--value: calc(--value + 10em);<\/code><\/li>\n<li>You can&#8217;t build-up values. The value has to be a valid CSS value for the given usage. So you <strong>can&#8217;t<\/strong> write:<br \/>\n<div class=\"code-embed-wrapper\"> <pre class=\"language-css code-embed-pre line-numbers\"  data-start=\"1\" data-line-offset=\"0\"><code class=\"language-css code-embed-code\">:root\u00a0{<br\/>    --unit: 8;<br\/>}<br\/><br\/>button {<br\/>    padding-top: var(--unit)px; \/* doesn&#039;t work *\/<br\/>}<\/code><\/pre> <div class=\"code-embed-infos\"> <\/div> <\/div><\/li>\n<li>You can use !important into Custom Properties values: <code>--value: 10px !important;<\/code> (but don&#8217;t\u2026)<\/li>\n<li>A blank character is a valid CSS Custom Properties value: <code>--value: ;<\/code> is valid, <code>--value:;<\/code> isn&#8217;t.<\/li>\n<li>You can have a fallback while using a variable: <code>color: var(--primary, #005533);<\/code><\/li>\n<li>A variable is a valid fallback: <code>color: var(--primary, var(--neutral, #005533));<\/code> and yes, it can be infinite.<\/li>\n<\/ul>\n<p>I hope this short transcript helped you a little bit. Don&#8217;t hesitate to contact me on <a href=\"https:\/\/twitter.com\/geoffreycrofte\">Twitter<\/a> if you need any advice.<\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Some years ago (2018 I think), I gave a talk during the JavaScript Meetup of Luxembourg where I presented briefly my interest for this new topic: CSS Variables. The official name of this specification is CSS Custom Properties. It allows you to store dynamic custom values to be used as CSS value within your code.<\/p>\n","protected":false},"author":4,"featured_media":7696,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"_bluesky_dont_syndicate":"","_bluesky_syndication_accounts":"","_bluesky_syndication_text":"","footnotes":""},"categories":[652],"tags":[903,804,901,902],"coauthors":[597],"class_list":["post-7692","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-css3","tag-conference-en","tag-css-variable","tag-custom-properties","tag-meetup"],"acf":[],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/www.creativejuiz.fr\/blog\/en\/wp-json\/wp\/v2\/posts\/7692","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.creativejuiz.fr\/blog\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.creativejuiz.fr\/blog\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.creativejuiz.fr\/blog\/en\/wp-json\/wp\/v2\/users\/4"}],"replies":[{"embeddable":true,"href":"https:\/\/www.creativejuiz.fr\/blog\/en\/wp-json\/wp\/v2\/comments?post=7692"}],"version-history":[{"count":3,"href":"https:\/\/www.creativejuiz.fr\/blog\/en\/wp-json\/wp\/v2\/posts\/7692\/revisions"}],"predecessor-version":[{"id":7698,"href":"https:\/\/www.creativejuiz.fr\/blog\/en\/wp-json\/wp\/v2\/posts\/7692\/revisions\/7698"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.creativejuiz.fr\/blog\/en\/wp-json\/wp\/v2\/media\/7696"}],"wp:attachment":[{"href":"https:\/\/www.creativejuiz.fr\/blog\/en\/wp-json\/wp\/v2\/media?parent=7692"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.creativejuiz.fr\/blog\/en\/wp-json\/wp\/v2\/categories?post=7692"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.creativejuiz.fr\/blog\/en\/wp-json\/wp\/v2\/tags?post=7692"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.creativejuiz.fr\/blog\/en\/wp-json\/wp\/v2\/coauthors?post=7692"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}