simurai simurai's site http://simurai.com Contextual styling with custom properties <p>Something I’ve been wanting for a long time, define different regions like a footer section, or side bar and not have to deal with all the contextual styling hassle. A.k.a. “Now that this button is used on a dark background, the button needs to change its colors too. Where should the styles live?”. Here an old post about <a href="http://simurai.com/blog/2015/05/11/nesting-components">struggling with contextual styling</a>.</p> <p>So then the other day I was doing <a href="https://github.com/atom/design-decisions/pull/4#issuecomment-356835247">some experiments</a> with using custom properties for Atom’s UI. Turns out, using custom properties might make contextual styling a bit easier. For the rest of the post, let’s switch to a more simple example. A page where the main area is light, but then has a dark hero and footer section. Like this:</p> <p><img height="300px" src="https://user-images.githubusercontent.com/378023/38169286-2fd31f54-35a1-11e8-8ae4-9e1fe892baf5.png" /></p> <p>In the past, I probably would’ve created variations like <code class="language-plaintext highlighter-rouge">Button--dark</code> or overwrote it with <code class="language-plaintext highlighter-rouge">header .Button {…}</code>. Depends a bit on the project. Here another approach: Create themes with a set of variables, then apply the theme to the different areas.</p> <h2 id="1-default-theme">1. Default theme</h2> <p>First let’s define our default theme with a bunch of variables.</p> <div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">[</span><span class="nt">data-theme</span><span class="o">=</span><span class="s1">"default"</span><span class="o">]</span> <span class="p">{</span> <span class="py">--fg</span><span class="p">:</span> <span class="n">hsl</span><span class="p">(</span><span class="m">0</span><span class="p">,</span><span class="m">0%</span><span class="p">,</span><span class="m">25%</span><span class="p">);</span> <span class="py">--border</span><span class="p">:</span> <span class="n">hsl</span><span class="p">(</span><span class="m">0</span><span class="p">,</span><span class="m">0%</span><span class="p">,</span><span class="m">75%</span><span class="p">);</span> <span class="py">--bg</span><span class="p">:</span> <span class="n">hsl</span><span class="p">(</span><span class="m">0</span><span class="p">,</span><span class="m">0%</span><span class="p">,</span><span class="m">95%</span><span class="p">);</span> <span class="py">--button-bg</span><span class="p">:</span> <span class="n">hsl</span><span class="p">(</span><span class="m">0</span><span class="p">,</span><span class="m">0%</span><span class="p">,</span><span class="m">99%</span><span class="p">);</span> <span class="py">--input-bg</span><span class="p">:</span> <span class="n">hsl</span><span class="p">(</span><span class="m">0</span><span class="p">,</span><span class="m">0%</span><span class="p">,</span><span class="m">90%</span><span class="p">);</span> <span class="p">}</span> </code></pre></div></div> <p>Then we create some components where we use the variables defined above.</p> <div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">[</span><span class="nt">data-theme</span><span class="o">]</span> <span class="p">{</span> <span class="nl">color</span><span class="p">:</span> <span class="n">var</span><span class="p">(</span><span class="n">--fg</span><span class="p">);</span> <span class="nl">background-color</span><span class="p">:</span> <span class="n">var</span><span class="p">(</span><span class="n">--bg</span><span class="p">);</span> <span class="p">}</span> <span class="nc">.Button</span> <span class="p">{</span> <span class="nl">color</span><span class="p">:</span> <span class="n">var</span><span class="p">(</span><span class="n">--fg</span><span class="p">);</span> <span class="nl">border</span><span class="p">:</span> <span class="m">1px</span> <span class="nb">solid</span> <span class="n">var</span><span class="p">(</span><span class="n">--border</span><span class="p">);</span> <span class="nl">background-color</span><span class="p">:</span> <span class="n">var</span><span class="p">(</span><span class="n">--button-bg</span><span class="p">);</span> <span class="p">}</span> <span class="nc">.Input</span> <span class="p">{</span> <span class="nl">color</span><span class="p">:</span> <span class="n">var</span><span class="p">(</span><span class="n">--fg</span><span class="p">);</span> <span class="nl">border</span><span class="p">:</span> <span class="m">1px</span> <span class="nb">solid</span> <span class="n">var</span><span class="p">(</span><span class="n">--border</span><span class="p">);</span> <span class="nl">background-color</span><span class="p">:</span> <span class="n">var</span><span class="p">(</span><span class="n">--input-bg</span><span class="p">);</span> <span class="p">}</span> </code></pre></div></div> <p>And lastly we add the <code class="language-plaintext highlighter-rouge">[data-theme="default"]</code> attribute on the body so that our components will pick up the variables.</p> <div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;body</span> <span class="na">data-theme=</span><span class="s">"default"</span><span class="nt">&gt;</span> </code></pre></div></div> <p>If you wonder why use <code class="language-plaintext highlighter-rouge">data-theme</code> attributes over classes? Well, no specific reason. Maybe with attributes, it’s a hint that only one theme should be used per element and is more separated from your other classes.</p> <p>At this point we get this:</p> <p data-height="340" data-theme-id="3586" data-slug-hash="be9c343986c1853c0487011d686678b7" data-default-tab="result" data-user="simurai" data-embed-version="2" data-pen-title="Contextual styling with custom properties (1/3)" class="codepen">See the Pen <a href="https://codepen.io/simurai/pen/be9c343986c1853c0487011d686678b7/">Contextual styling with custom properties (1/3)</a> by simurai (<a href="https://codepen.io/simurai">@simurai</a>) on <a href="https://codepen.io">CodePen</a>.</p> <script async="" src="https://static.codepen.io/assets/embed/ei.js"></script> <h2 id="2-dark-theme">2. Dark theme</h2> <p>But our designer wants the hero and footer to be dark. Alright, let’s define another theme region.</p> <div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">[</span><span class="nt">data-theme</span><span class="o">=</span><span class="s1">"dark"</span><span class="o">]</span> <span class="p">{</span> <span class="py">--fg</span><span class="p">:</span> <span class="n">hsl</span><span class="p">(</span><span class="m">0</span><span class="p">,</span><span class="m">10%</span><span class="p">,</span><span class="m">70%</span><span class="p">);</span> <span class="py">--border</span><span class="p">:</span> <span class="n">hsl</span><span class="p">(</span><span class="m">0</span><span class="p">,</span><span class="m">10%</span><span class="p">,</span><span class="m">10%</span><span class="p">);</span> <span class="py">--bg</span><span class="p">:</span> <span class="n">hsl</span><span class="p">(</span><span class="m">0</span><span class="p">,</span><span class="m">0%</span><span class="p">,</span><span class="m">20%</span><span class="p">);</span> <span class="py">--button-bg</span><span class="p">:</span> <span class="n">hsl</span><span class="p">(</span><span class="m">0</span><span class="p">,</span><span class="m">0%</span><span class="p">,</span><span class="m">25%</span><span class="p">);</span> <span class="py">--input-bg</span><span class="p">:</span> <span class="n">hsl</span><span class="p">(</span><span class="m">0</span><span class="p">,</span><span class="m">0%</span><span class="p">,</span><span class="m">15%</span><span class="p">);</span> <span class="p">}</span> </code></pre></div></div> <p>And add the theme attribute to the header and footer.</p> <div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;header</span> <span class="na">data-theme=</span><span class="s">"dark"</span><span class="nt">&gt;</span> <span class="nt">&lt;footer</span> <span class="na">data-theme=</span><span class="s">"dark"</span><span class="nt">&gt;</span> </code></pre></div></div> <p>Which gives us this:</p> <p data-height="340" data-theme-id="3586" data-slug-hash="b7a9532fe4607536b4c8acb659fbcabe" data-default-tab="result" data-user="simurai" data-embed-version="2" data-pen-title="Contextual styling with custom properties (2/3)" class="codepen">See the Pen <a href="https://codepen.io/simurai/pen/b7a9532fe4607536b4c8acb659fbcabe/">Contextual styling with custom properties (2/3)</a> by simurai (<a href="https://codepen.io/simurai">@simurai</a>) on <a href="https://codepen.io">CodePen</a>.</p> <script async="" src="https://static.codepen.io/assets/embed/ei.js"></script> <p>The reason why this works is that custom properties cascade and can be overridden on nested elements, just like normal properties.</p> <h2 id="3-hero-theme">3. Hero theme</h2> <p>A few months pass and our designer comes back with a redesigned hero section. “To make it look fresh” with a splash of color.</p> <p>No problem! Just like with the dark theme, we define a new “hero” theme.</p> <div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">[</span><span class="nt">data-theme</span><span class="o">=</span><span class="s1">"hero"</span><span class="o">]</span> <span class="p">{</span> <span class="py">--fg</span><span class="p">:</span> <span class="n">hsl</span><span class="p">(</span><span class="m">240</span><span class="p">,</span><span class="m">50%</span><span class="p">,</span><span class="m">90%</span><span class="p">);</span> <span class="py">--border</span><span class="p">:</span> <span class="n">hsl</span><span class="p">(</span><span class="m">240</span><span class="p">,</span><span class="m">50%</span><span class="p">,</span><span class="m">10%</span><span class="p">);</span> <span class="py">--bg</span><span class="p">:</span> <span class="n">hsl</span><span class="p">(</span><span class="m">240</span><span class="p">,</span><span class="m">33%</span><span class="p">,</span><span class="m">30%</span><span class="p">);</span> <span class="py">--button-bg</span><span class="p">:</span> <span class="n">hsl</span><span class="p">(</span><span class="m">240</span><span class="p">,</span><span class="m">33%</span><span class="p">,</span><span class="m">40%</span><span class="p">);</span> <span class="py">--input-bg</span><span class="p">:</span> <span class="n">hsl</span><span class="p">(</span><span class="m">240</span><span class="p">,</span><span class="m">33%</span><span class="p">,</span><span class="m">20%</span><span class="p">);</span> <span class="p">}</span> </code></pre></div></div> <div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;header</span> <span class="na">data-theme=</span><span class="s">"hero"</span><span class="nt">&gt;</span> </code></pre></div></div> <p>And here is that fresh hero:</p> <p data-height="340" data-theme-id="3586" data-slug-hash="c995ced84077d0823a1496ee6fbacd27" data-default-tab="result" data-user="simurai" data-embed-version="2" data-pen-title="Contextual styling with custom properties (3/3)" class="codepen">See the Pen <a href="https://codepen.io/simurai/pen/c995ced84077d0823a1496ee6fbacd27/">Contextual styling with custom properties (3/3)</a> by simurai (<a href="https://codepen.io/simurai">@simurai</a>) on <a href="https://codepen.io">CodePen</a>.</p> <script async="" src="https://static.codepen.io/assets/embed/ei.js"></script> <p>It’s also not limited to colors only, could be used for sizes, fonts or anything that makes sense to define as variables.</p> <h2 id="benefits">Benefits</h2> <p>Using these theme “regions” lets your components stay context <strong>un-aware</strong> and you can use them in multiple themes. Even on the same page.</p> <ul> <li>Developers can add components, move components around, without having to know about in what context (theme) they live. The <strong>markup</strong> for the components <strong>stays the same</strong>.</li> <li>Design systems authors can create new components without worrying about where they get used, the <strong>variables</strong> used in components <strong>stay the same</strong>.</li> <li>Designers can define new theme regions, or change existing ones, without having to make changes to a component’s <strong>HTML or CSS</strong>, it <strong>stays the same</strong>.</li> </ul> <p>Less time to talk about who, how and where, more time to talk about the weather. ☔️🙃</p> <h2 id="concerns">Concerns</h2> <p>Yeah, right. The big question: But does it scale? Can this be used for all use cases.</p> <p>Ok, I’m pretty sure it doesn’t fit all situations. There are just too many to find a single solution for them all. And I’m actually not sure how well it scales. I guess it works great in these simple demos, but I have yet to find a larger project to test it on. So if you have used (or plan to use) this approach, I’m curious to know how it went.</p> <p>A concern I can imagine is that the list of variables might grow quickly if themes have totally different characteristics. Like not just a bit darker or lighter backgrounds. Then you might need to have foreground and border colors for each component (or group of components) and can’t just use the general <code class="language-plaintext highlighter-rouge">--fg</code> and <code class="language-plaintext highlighter-rouge">--border</code> variables. Naming these variables is probably the hardest part.</p> <h2 id="update-i">Update I</h2> <p><a href="https://twitter.com/giuseppegurgone">@giuseppegurgone</a> made an interesting <a href="https://twitter.com/giuseppegurgone/status/980398653453021184">comment</a>:</p> <blockquote> <p>in suitcss projects I used to define component level custom props, theme variables and then create themes by mapping the former to the latter <a href="https://github.com/giuseppeg/suitcss-toolkit/tree/example-app/examples/app#themes">suitcss-toolkit</a></p> </blockquote> <p>So if I understood it correctly, by mapping theme variables to component variables, you could avoid your theme variables from growing too much and you can decide for each component how to use these theme variables.</p> <h2 id="update-ii">Update II</h2> <p>If it’s too early to use custom properties in your project, <a href="https://github.com/szalonna">@szalonna</a> posted an <a href="https://github.com/simurai/simurai.github.io/issues/13">example</a> how to do something similar in SCSS.</p> Sun, 01 Apr 2018 00:00:00 +0000 http://simurai.com/blog/2018/04/01/contextual-styling http://simurai.com/blog/2018/04/01/contextual-styling DuoTone themes <p><img src="/img/posts/duotone-dark.png" alt="DuoTone themes" /></p> <p>Double-hue syntax themes for <strong>Atom</strong>.</p> <p>DuoTone themes use only 2 hues (7 shades in total). It <strong>tones down</strong> less important parts (like punctuation and brackets) and highlights only the <strong>important</strong> ones. This leads to a more calm color scheme, but still lets you find the stuff you’re looking for.</p> <p>A <strong>big thanks</strong> goes to <a href="https://github.com/braver">@braver</a> who did most of the initial <a href="https://github.com/simurai/duotone-dark-syntax/pull/2">language support</a>.</p> <h2 id="color-variations">Color variations</h2> <p><a href="http://simurai.com/duotone-dark-sky-syntax"><img src="/img/posts/duotone-dark.png" alt="DuoTone dark" /></a> <a href="http://simurai.com/duotone-dark-sea-syntax"><img src="/img/posts/duotone-dark-sea.png" alt="DuoTone dark Sea" /></a> <a href="http://simurai.com/duotone-dark-space-syntax"><img src="/img/posts/duotone-dark-space.png" alt="DuoTone dark Space" /></a> <a href="http://simurai.com/duotone-dark-earth-syntax"><img src="/img/posts/duotone-dark-earth.png" alt="DuoTone dark Earth" /></a> <a href="http://simurai.com/duotone-dark-forest-syntax"><img src="/img/posts/duotone-dark-forest.png" alt="DuoTone dark Forest" /></a></p> <p>And here some more <a href="https://atom.io/themes/search?utf8=%E2%9C%93&amp;q=keyword:duotone">color variations</a> created by other theme authors.</p> Fri, 01 Jan 2016 00:00:00 +0000 http://simurai.com/projects/2016/01/01/duotone-themes http://simurai.com/projects/2016/01/01/duotone-themes Back to the :roots <p>The cascade in CSS is a curse and blessing at the same time. It usually works quite well, but there are issues that let people get all worked up and ask the question <a href="https://css-tricks.com/the-debate-around-do-we-even-need-css-anymore/">Do We Even Need CSS Anymore</a>. I can somewhat relate to that - but I also think it’s not the cascade alone and also about fighting specificity. Not running into issues with specificity is hard. Almost as hard as pronouncing that word.</p> <p>In this post I’ll try to show a few ways how you can make the cascade be your friend and maybe reduce the need of overriding and thus encounter less fighting with specificity.</p> <h2 id="tip-1">Tip 1:</h2> <blockquote> <p>For every CSS property that you write, try to move it up the tree as far as possible. In other words: Back to the :root.</p> </blockquote> <p>For example, our site has a side bar and we want to add a short bio to it. The markup might look something like this:</p> <div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;body&gt;</span> <span class="nt">&lt;main</span> <span class="na">class=</span><span class="s">“Posts”</span><span class="nt">&gt;</span> <span class="nt">&lt;aside</span> <span class="na">class=</span><span class="s">“SideBar”</span><span class="nt">&gt;</span> <span class="nt">&lt;nav</span> <span class="na">class=</span><span class="s">“Nav”</span><span class="nt">&gt;</span> <span class="nt">&lt;p</span> <span class="na">class=</span><span class="s">“Bio”</span><span class="nt">&gt;</span> </code></pre></div></div> <p>And the CSS:</p> <div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.Bio</span> <span class="p">{</span> <span class="nl">font-size</span><span class="p">:</span> <span class="m">.8em</span><span class="p">;</span> <span class="nl">line-height</span><span class="p">:</span> <span class="m">1.5</span><span class="p">;</span> <span class="nl">color</span><span class="p">:</span> <span class="m">#888</span><span class="p">;</span> <span class="p">}</span> </code></pre></div></div> <p>That would work. But if we look at the Nav that is already in the SideBar, chances are good that some of the styles are the same. In our case it’s <code class="language-plaintext highlighter-rouge">font-size</code> and <code class="language-plaintext highlighter-rouge">color</code>. So let’s remove those properties from Nav and Bio and add it to the shared parent element, the SideBar.</p> <div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.SideBar</span> <span class="p">{</span> <span class="nl">font-size</span><span class="p">:</span> <span class="m">.8em</span><span class="p">;</span> <span class="nl">color</span><span class="p">:</span> <span class="m">#888</span><span class="p">;</span> <span class="p">}</span> </code></pre></div></div> <p>And as it turns out, that <code class="language-plaintext highlighter-rouge">line-height: 1.5;</code> is already defined for our Posts. So since it seems that the whole page uses the same line-height, let’s remove it from the Bio and Post elements and move it all up to the root node.</p> <div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nd">:root</span> <span class="p">{</span> <span class="nl">line-height</span><span class="p">:</span> <span class="m">1.5</span><span class="p">;</span> <span class="p">}</span> </code></pre></div></div> <p>This probably sounds like common sense, but often it’s tempting to just style your new thing without even looking if some of the sibling elements define the same thing. This also happens when you copy&amp;paste styles from another section or when pasting some snippets you found online. It might take a bit more time to refactor and seems scary, but it should keep our CSS in a healthier state.</p> <p><img src="/img/posts/roots-1.png" alt="inline vs cascade" /></p> <blockquote> <p>Style the branches, not each leaf</p> </blockquote> <hr /> <h2 id="tip-2">Tip 2:</h2> <blockquote> <p>Style certain properties always as a <strong>combo</strong>.</p> </blockquote> <p>A good example is the <code class="language-plaintext highlighter-rouge">color</code> and <code class="language-plaintext highlighter-rouge">background-color</code> combo. Unless you make only small tweaks, it’s probably a good idea to always change them together. When adding a background color to an element, it might not contain any text, but probably some child will. Therefore if we set foreground and background color together, we can always be sure we won’t run into any legibility and contrast issues. Also, next time we change a background color, we don’t have to hunt for all the text colors that need to be changed too, it’s right there in the same place.</p> <p><img src="/img/posts/roots-2.png" alt="Contrast" /></p> <blockquote> <p>Screenshot from <a href="http://jxnblk.com/colorable/demos/text/">Colorable</a></p> </blockquote> <hr /> <h2 id="tip-3">Tip 3:</h2> <blockquote> <p>Use “dynamic” values, such as <code class="language-plaintext highlighter-rouge">currentColor</code> and <code class="language-plaintext highlighter-rouge">em</code>s.</p> </blockquote> <p>Sometimes it might make sense to use the text <code class="language-plaintext highlighter-rouge">color</code> for other properties. Like for <code class="language-plaintext highlighter-rouge">border</code>, <code class="language-plaintext highlighter-rouge">box-shadow</code> or for the <code class="language-plaintext highlighter-rouge">fill</code> of SVG icons. Instead of defining them directly you can use <code class="language-plaintext highlighter-rouge">currentColor</code> and it will be the same the <code class="language-plaintext highlighter-rouge">color</code> property. And since <code class="language-plaintext highlighter-rouge">color</code> inherits by default, you might can change it in only one place.</p> <p>Similarly <code class="language-plaintext highlighter-rouge">em</code>s are mapped to <code class="language-plaintext highlighter-rouge">font-size</code> allowing you to scale everything by just changing the :root font size.</p> <p>Here a few more details on <a href="http://simurai.com/blog/2014/05/04/cssconf">currentColor and EMs</a>.</p> <p><img src="/img/posts/cssconf-size.gif" alt="EMs" /></p> <hr /> <h2 id="tip-4">Tip 4:</h2> <blockquote> <p>Override UA Styles to <code class="language-plaintext highlighter-rouge">inherit</code> from its parents.</p> </blockquote> <p>Form controls like buttons, inputs get styled by the browser in a certain way. Overriding them with <code class="language-plaintext highlighter-rouge">inherit</code> makes them adapt to your own styles.</p> <div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">button</span><span class="o">,</span> <span class="nt">input</span><span class="o">,</span> <span class="nt">select</span><span class="o">,</span> <span class="nt">textarea</span> <span class="p">{</span> <span class="nl">color</span><span class="p">:</span> <span class="nb">inherit</span><span class="p">;</span> <span class="nl">font-family</span><span class="p">:</span> <span class="nb">inherit</span><span class="p">;</span> <span class="nl">font-style</span><span class="p">:</span> <span class="nb">inherit</span><span class="p">;</span> <span class="nl">font-weight</span><span class="p">:</span> <span class="nb">inherit</span><span class="p">;</span> <span class="p">}</span> </code></pre></div></div> <p>The example above is taken from <a href="https://10up.github.io/sanitize.css/">sanitize.css</a>. <a href="https://necolas.github.io/normalize.css/">normalize.css</a> does the same, so if you use them, you’re already covered.</p> <p>You can also try to restyle other inputs like a range slider, radio, checkbox etc. And as seen above, by using <code class="language-plaintext highlighter-rouge">currentColor</code>, make them automatically match the color property. And maybe move them from a light into a dark theme without changing anything.</p> <p><img src="/img/posts/cssconf-color3.gif" alt="root coloring" /></p> <h2 id="conclusion">Conclusion</h2> <p>That’s all nice stuff, but who is it for? Well, of course it can’t be forced upon every situation. I would say small and simple web sites benefit the most. But even when using a preprocessor, it might not hurt if it reduces the amount of CSS that gets output or when a few variables aren’t even needed.</p> <p>Also it seems suited for the “single purpose class” approach like <a href="http://tachyons.io/">Tachyons</a>. It might reduce complexity and the amount of classes that are needed.</p> <p>Another interesting thing could be the upcoming custom properties a.k.a. CSS variables. Unlike variables in preprocessors, when overriding a custom property, it will only affect the current selector scope. So in a sense they will be “cascading variables”. But I still have to try that out and see how it works in practice.</p> <p>ps. It is possible that this post is inspired by this <a href="https://twitter.com/kaelig/status/616902099457175552">tweet</a>.</p> Wed, 09 Sep 2015 00:00:00 +0000 http://simurai.com/blog/2015/09/09/back-to-the-roots http://simurai.com/blog/2015/09/09/back-to-the-roots Nesting Components <p>Using CSS components is somewhat straightforward. We add the markup and give it the component’s class name and all is good. Where it gets trickier is when we try to nest components. And when they need to be tweaked based on the context. Where should the styles be defined? It’s a question I’ve been asking myself a few times and what this article is trying to explore.</p> <blockquote> <p>Just to clarify before we start, with “CSS components”, I mean the small building blocks that get used to assemble a website or app. Like buttons, inputs, navs, headers etc. Some also call them modules or patterns. Also I’m using the <a href="https://github.com/suitcss/suit/blob/master/doc/naming-conventions.md">SUIT</a> naming convention in the examples below, but any other convention would be fine as well. And just a heads, there isn’t some awesome solution at the end that solves all the problems. It’s just me whining most of the time.</p> </blockquote> <p>Ok, best is to go straight into it and look at an example. Let’s say we have a Header component where we would like to add a Button component inside.</p> <div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;header</span> <span class="na">class=</span><span class="s">“Header”</span><span class="nt">&gt;</span> <span class="nt">&lt;button</span> <span class="na">class=</span><span class="s">“Button”</span><span class="nt">&gt;</span>Button<span class="nt">&lt;/button&gt;</span> <span class="nt">&lt;/header&gt;</span> </code></pre></div></div> <p>Now because the Button is inside the Header, we want to make the Button a bit smaller than it would be on its own.</p> <p><img src="/img/posts/nesting-components-1.png" alt="Button in Header" /></p> <p>Here a few approaches how to do that:</p> <h2 id="option-1---descendant-selector">Option 1 - Descendant selector</h2> <p>Maybe the most common way is to use a descendant selector to change the <code class="language-plaintext highlighter-rouge">font-size</code> whenever a Button is inside a Header.</p> <div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.Header</span> <span class="nc">.Button</span> <span class="p">{</span> <span class="nl">font-size</span><span class="p">:</span> <span class="m">.75em</span><span class="p">;</span> <span class="p">}</span> </code></pre></div></div> <p>This works great but the question is, where should this rule be added? We probably split our components into separate files, so is it in <code class="language-plaintext highlighter-rouge">header.scss</code> or in <code class="language-plaintext highlighter-rouge">button.scss</code>? In other words, should the Header know about what other components might get nested or should the Button know in what environment it will get placed?</p> <p>But wait, the point of creating components is to separate them, make them modular. Each component should be kept isolated and shouldn’t know about other components. So we can make changes, rename or remove them without having to check if they might get used somewhere else.</p> <h2 id="option-2---variations">Option 2 - Variations</h2> <p>Another way is to create variations. We add a <code class="language-plaintext highlighter-rouge">.Button--small</code> class that we can use whenever we would like the button to be smaller without having to worry about ancestors.</p> <div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.Button--small</span> <span class="p">{</span> <span class="nl">font-size</span><span class="p">:</span> <span class="m">.75em</span><span class="p">;</span> <span class="p">}</span> </code></pre></div></div> <div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;header</span> <span class="na">class=</span><span class="s">“Header”</span><span class="nt">&gt;</span> <span class="nt">&lt;button</span> <span class="na">class=</span><span class="s">“Button</span> <span class="na">Button--small</span><span class="err">”</span><span class="nt">&gt;</span>Button<span class="nt">&lt;/button&gt;</span> <span class="nt">&lt;/header&gt;</span> </code></pre></div></div> <p>This works great too, but could get out of hand quickly. What do you do if at some point you want the <code class="language-plaintext highlighter-rouge">font-size</code> to be <code class="language-plaintext highlighter-rouge">.9em</code>? Create yet another variation? <code class="language-plaintext highlighter-rouge">Button--justALittleSmaller</code>. As the project keeps growing, the number of variations will too. We will start to loose sight where they actually get used and we’re not sure anymore if we can change a variation or if it will have <a href="http://philipwalton.com/articles/side-effects-in-css/">side effects</a> in some other place. We could create “contextual” variations like <code class="language-plaintext highlighter-rouge">Button--header</code> or <code class="language-plaintext highlighter-rouge">Button--footer</code>, but then we’re back at the beginning and could just as well use “descendant selectors”.</p> <p>Same goes for using states. <code class="language-plaintext highlighter-rouge">.Button.is-small</code> should only be used if there is a change in state and not to fit a certain context.</p> <h2 id="option-3---adopted-child">Option 3 - Adopted Child</h2> <p>I can’t remember where I read about this approach but somehow it stuck with me. I also forgot how it was called. So for now I’ll just call it “Adopted Child”.</p> <p>Let’s switch it around and look at it from the Header’s perspective. What would we do if we wouldn’t know what the components are called that might get nested? But we know that we want to make them a bit smaller. Well, we probably would create a generic <code class="language-plaintext highlighter-rouge">.Header-item</code> class and use it like this:</p> <div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.Header-item</span> <span class="p">{</span> <span class="nl">font-size</span><span class="p">:</span> <span class="m">.75em</span><span class="p">;</span> <span class="p">}</span> </code></pre></div></div> <div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;header</span> <span class="na">class=</span><span class="s">“Header”</span><span class="nt">&gt;</span> <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">“Header-item”</span><span class="nt">&gt;&lt;/div&gt;</span> <span class="nt">&lt;/header&gt;</span> </code></pre></div></div> <p>Ok, that gets us a bit closer. Now, it’s probably strange saying it like that when talking about CSS, but what would we do if we don’t want to create an own child, but still have one. Right, we could adopt one. In our example we adopt a Button component as our own child. We didn’t create it, but now we can tweak.. erm.. I mean “raise” it like it’s our own:</p> <div class="language-scss highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// born in button.scss</span> <span class="nc">.Button</span> <span class="p">{</span> <span class="nl">font-size</span><span class="p">:</span> <span class="m">1em</span><span class="p">;</span> <span class="p">}</span> <span class="c1">// raised in header.css</span> <span class="nc">.Header</span> <span class="nc">.Header-item</span> <span class="p">{</span> <span class="nl">font-size</span><span class="p">:</span> <span class="mi">.75em</span><span class="p">;</span> <span class="p">}</span> </code></pre></div></div> <div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;header</span> <span class="na">class=</span><span class="s">“Header”</span><span class="nt">&gt;</span> <span class="nt">&lt;button</span> <span class="na">class=</span><span class="s">“Header-item</span> <span class="na">Button</span><span class="err">”</span><span class="nt">&gt;</span>Button<span class="nt">&lt;/button&gt;</span> <span class="nt">&lt;/header&gt;</span> </code></pre></div></div> <p>It is a bit uncommon that the same HTML element shares classes from two different components. And it’s not without any risks. More about them later. But I really like this approach because it keeps the components independent without having to know about each other.</p> <p>Another nice thing is that if we want to add other components to the Header that also need the same adjustments, we can reuse the same <code class="language-plaintext highlighter-rouge">Header-item</code> class, like for example on a text Input.</p> <div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;header</span> <span class="na">class=</span><span class="s">“Header”</span><span class="nt">&gt;</span> <span class="nt">&lt;input</span> <span class="na">class=</span><span class="s">“Header-item</span> <span class="na">Input</span><span class="err">”</span><span class="nt">&gt;</span> <span class="nt">&lt;button</span> <span class="na">class=</span><span class="s">“Header-item</span> <span class="na">Button</span><span class="err">”</span><span class="nt">&gt;</span>Button<span class="nt">&lt;/button&gt;</span> <span class="nt">&lt;/header&gt;</span> </code></pre></div></div> <p><img src="/img/posts/nesting-components-2.png" alt="Button and Input in Header" /></p> <p>Ok, about those risks. Well, depending on what properties we wanna change, it might not always be ideal. For example, because the Button already had <code class="language-plaintext highlighter-rouge">font-size</code> defined, we had to increase specificity by using <code class="language-plaintext highlighter-rouge">.Header .Header-item</code>. But that would also override variations like <code class="language-plaintext highlighter-rouge">.Button--small</code>. That might be how we want it, but there are also situations where we’d like the variation to always be “stronger”. An example would be when changing colors. When the color of Buttons should be different inside a Header, but not when its a variation, like <code class="language-plaintext highlighter-rouge">.Button—primary</code>. Yeah, we could take a look inside button.scss or our style-guide, but remember our goal.. we actually don’t want to make decisions by looking how other components are made.</p> <p>So, as a general rule, don’t use “adopted children” for any properties that are theme related and only where you can be sure that you want to override them all the time. Like for layout/size related properties or adjusting the position.</p> <h2 id="more-options">More options?</h2> <p>There are some more ways to do contextual styling that came to mind. I’ll just mention them briefly for completeness, but think the 3 above are better suited.</p> <p><strong>Option 4</strong> - We could use a preprocessor to <strong>extend</strong> an existing component. In our example it would be a clone of the Button with some tweaks added and used as a new child component <code class="language-plaintext highlighter-rouge">.Header-button</code>. Now we only rely that the Button exists in the source, but don’t have to worry about other contexts. Downside is inflating our CSS output. As well as having to remember lots of new child component classes.</p> <p><strong>Option 5</strong> - We could create a <strong>utility</strong> class like <code class="language-plaintext highlighter-rouge">.u-small</code>. It’s similar to variations, but not scoped to a single component and could be used for other components as well. And for that reason it becomes very risky to ever change later.</p> <p><strong>Option 6</strong> - And of course, we could use <strong>inline styles</strong>. But I would leave that to JavaScript only.</p> <hr /> <p>So after all that, which is best? I’m afraid there isn’t a clear winner. It would be nice to keep it consistent with a single approach throughout the entire project, but I guess we just have to decide on a per case basis:</p> <ol> <li><strong>Descendant selectors</strong> if we can expect that components don’t change much. Like when using a UI Kit or library.</li> <li><strong>Variations</strong> if it makes sense that a component has different versions that get reused anyways, and not just for a specific context.</li> <li><strong>Adopted Child</strong> for layout, sizing, positioning or where we are sure to always want to override a property. Also for changing multiple child components at once.</li> <li><strong>Extending</strong> when we truly want the components to be separated and don’t mind inflating the CSS output.</li> <li><strong>Utilities</strong> for very specific things, that once the class is defined, it will never change, like clearing floats.</li> <li><strong>Inline styles</strong> if it needs to be dynamically added with JavaScript.</li> </ol> <p>As said at the beginning, I haven’t found a “fits all” solution and maybe the conclusion is: Try to keep contextual styling to a minimum.</p> <h2 id="updates">Updates</h2> <p>The “Adopted Child” approach is called “Mixes” in BEM. Here some <a href="https://en.bem.info/forum/issues/4/">more infos</a>.</p> <hr /> <p>SUIT also <a href="https://github.com/suitcss/suit/blob/master/doc/components.md#styling-dependencies">recommends</a> using “Adopted Child/Mixes”. But also another option:</p> <p><strong>Option 7</strong> - Adding a <strong>wrapper element</strong>. It’s the <code class="language-plaintext highlighter-rouge">&lt;div class="Excerpt-wrapButton"&gt;</code> in that <a href="https://github.com/suitcss/suit/blob/master/doc/components.md#styling-dependencies">example</a>. I think it works great in most cases. But for example when using Flexbox, because it has this parent/child relationship, adding an extra wrapper in between would break it. And then you might still need to set the width of the wrapped component to 100% or so. Anyways, this is a great addition. Thanks Pablo in the comments.</p> <hr /> <p><strong>Option 8</strong> - <strong>Single Purpose Classes</strong>. It’s where every class has only a single property. It’s somewhere between utilities (Option 5) and inline styles (Option 6). <a href="http://acss.io">Atomic CSS</a> and <a href="http://tachyons.io/">Tachyons</a> use this approach. I haven’t used them on a real project, but just from looking at it, the concerns are similar to the ones from utilities. If you want to change the value in a SP class, it seems unpredictable. Because in another place (where that same class is used), you might want to keep the current value. So you would have to first check if the change has any unwanted effects somewhere else.</p> Mon, 11 May 2015 00:00:00 +0000 http://simurai.com/blog/2015/05/11/nesting-components http://simurai.com/blog/2015/05/11/nesting-components FrontLinks <p>This is my (living) collection of <strong>front-end</strong> links. It’s not complete by all means, in fact, there isn’t any of the obvious ones, like <a href="http://caniuse.com">Can I use</a> or so. Just some links that I need occasionally but can’t remember their names, so I saved them here for quick access. Also, they’re somewhat randomly ordered.</p> <blockquote> <p>Note to self: <a href="https://github.com/simurai/simurai.github.io/edit/master/_posts/2014-10-01-front-links.md">Edit source</a></p> </blockquote> <h2 id="docs">Docs</h2> <ul> <li><a href="http://htmlreference.io/">HTML reference</a></li> <li><a href="http://devdocs.io/">DevDocs</a></li> <li><a href="http://nativeformelements.com/">Native HTML Elements</a></li> <li><a href="http://youmightnotneedjquery.com/">jQuery -&gt; JS</a></li> <li><a href="http://fontfamily.io/">Default Font Family</a></li> <li>Shadow DOM <ul> <li><a href="https://gist.github.com/3759334">The list</a></li> <li><a href="http://tjvantoll.com/2013/04/15/list-of-pseudo-elements-to-style-form-controls/">Form Pseudo Elements</a></li> </ul> </li> <li><a href="http://www.google.com/design/tool/devices/">Device sizes</a></li> <li><a href="https://github.com/jonitrythall/svgpocketguide/blob/master/svgpocketguide.md">SVG PocketGuide</a></li> </ul> <h2 id="css">CSS</h2> <ul> <li><a href="http://cssreference.io/">CSS reference</a></li> <li><a href="http://ref.openweb.io/CSS/">All CSS properties</a></li> <li><a href="https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_values_syntax">All CSS values</a></li> <li> <p><a href="http://csstriggers.com/">CSS Triggers (perf)</a></p> </li> <li>Stats <ul> <li><a href="http://stylestats.org/">StyleStats</a></li> <li><a href="http://cssstats.com/">CSS Stats</a></li> </ul> </li> <li>CSS Preprocessors <ul> <li><a href="http://roole.org/">Roole</a></li> <li><a href="http://sebastianpontow.de/css2compass/">CSS to SCSS</a></li> </ul> </li> <li>FlexBox <ul> <li><a href="http://jonibologna.com/flexbox-cheatsheet/">cheatsheet</a></li> <li><a href="https://scotch.io/demos/visual-guide-to-css3-flexbox-flexbox-playground">Flexbox Playground</a></li> <li><a href="http://webkit-flex.atomeye.com/">Patterns</a></li> <li><a href="http://flexboxin5.com/">Flexbox in 5min</a></li> <li><a href="http://bennettfeely.com/flexplorer/">Flexplorer</a></li> <li><a href="http://the-echoplex.net/flexyboxes/">FlexyBoxes</a></li> </ul> </li> <li>Animation <ul> <li><a href="http://bouncejs.com/">Bounce.js</a></li> <li><a href="http://jeremyckahn.github.io/stylie/">Stylie</a></li> </ul> </li> <li>Easing: <ul> <li><a href="https://easingwizard.com/">Easing Wizard</a></li> <li><a href="http://www.roblaplaca.com/examples/bezierBuilder/">Bezier Builder</a></li> <li><a href="http://matthewlein.com/ceaser/">Ceaser</a></li> <li><a href="http://cubic-bezier.com/">cubic-bezier</a></li> <li><a href="http://easings.net/">Easings</a></li> </ul> </li> <li>nth-child <ul> <li><a href="http://nth-test.com/">nth-test</a></li> <li><a href="http://codepen.io/RadLikeWhoa/full/cAJEo#tool">:kids</a></li> </ul> </li> <li>Color <ul> <li><a href="http://briangrinstead.com/colorstash/">Color converter</a></li> <li><a href="http://jxnblk.com/colorable/demos/text/">Contrast tester</a></li> </ul> </li> <li><a href="http://bennettfeely.com/clippy/">Clip Path</a></li> <li><a href="http://matthewkosloski.me/labs/pixem/">px to em</a></li> <li><a href="http://chrisnager.github.io/cursors/">Cursors</a></li> <li>Live Edit <ul> <li><a href="http://usetakana.com/">Takana</a></li> <li><a href="http://livestyle.emmet.io/">Emmet</a></li> </ul> </li> </ul> <h2 id="libs--frameworks">Libs + Frameworks</h2> <ul> <li><a href="https://developers.google.com/web/starter-kit/">Web Starter Kit</a></li> <li><a href="http://vuejs.org/">vue.js</a></li> <li><a href="http://impulse.luster.io/">Physics Animation</a></li> <li><a href="http://anijs.github.io/">AniJS</a></li> <li><a href="https://popmotion.io/">Popmotion</a></li> </ul> <h2 id="utils--tools">Utils + Tools</h2> <ul> <li>Wireframes <ul> <li><a href="https://whimsical.co/wireframes/">Whimsical</a></li> <li><a href="http://wireframe.cc/">wireframe.cc</a></li> <li><a href="https://moqups.com/">Moqups</a></li> </ul> </li> <li>HTML symbols <ul> <li><a href="http://copypastecharacter.com/">☺ Characters</a></li> <li><a href="http://shapecatcher.com/">Draw Chars</a></li> </ul> </li> <li><a href="http://placehold.it/">Placeholder Image</a></li> <li><a href="http://www.xiconeditor.com/">FavIcon Editor</a></li> <li>SVG <ul> <li><a href="https://jakearchibald.github.io/svgomg/">SVG Optimizer</a></li> <li><a href="http://jxnblk.com/paths/">Paths (editor)</a></li> </ul> </li> <li><a href="http://prose.io/">GitHub Editor</a></li> </ul> <h2 id="resources">Resources</h2> <ul> <li><a href="http://colorhunt.co/">Color schemes</a></li> <li>Fonts <ul> <li><a href="http://www.typewolf.com/">Font Guide</a></li> <li><a href="http://katydecorah.com/font-library/">Tagged Google Fonts</a></li> <li><a href="http://blokkfont.com">Blokk Font</a></li> </ul> </li> <li>Icons <ul> <li><a href="https://feathericons.com/">Feather</a></li> <li><a href="http://icomoon.io/app/">Icomoon</a></li> <li><a href="https://www.google.com/design/icons/">Material</a></li> <li><a href="http://entypo.com/characters/">Entypo</a></li> </ul> </li> <li>Photos <ul> <li><a href="http://www.splashbase.co/">SplashBase</a></li> <li><a href="http://www.sitebuilderreport.com/stock-up">Stock Up</a></li> <li><a href="https://medium.com/design-ux/62ae4bcbe01b">Unsucky Stock Photos</a></li> </ul> </li> <li><a href="http://subtlepatterns.com/">Subtle Patterns</a></li> <li><a href="https://soundkit.io/">UI Sounds</a></li> </ul> Wed, 01 Oct 2014 00:00:00 +0000 http://simurai.com/blog/2014/10/01/front-links http://simurai.com/blog/2014/10/01/front-links Filtering (photo) filters <p>A lot of photo apps allow you to add filters before sharing. The typical UI for picking a filter is a row of little <strong>thumbnails</strong> that can be <strong>horizontally scrolled</strong>. I’m sure you’ve used it many times. It looks something like this:</p> <p><img src="/img/posts/filter-1.jpg" alt="Photo filter" /></p> <h2 id="the-problem">The problem</h2> <p>A filter picker like that is easy to understand and works pretty well. But in my case, there is something that has been bugging me a bit. Here is how I use it:</p> <ol> <li>I start with the first thumbnail and then just keep tapping <strong>one after the other</strong>.</li> <li>If there is a filter that I like, I try to remember its <strong>name</strong>. And somewhat its position, but more like “somewhere at the beginning”.</li> <li>Then once I reach the end, I start scrolling back trying to <strong>find</strong> the ones I liked.</li> <li>Usually there are like 2-3 filters that I would like to quickly <strong>compare</strong> before making my final choice. But it’s quite hard to scroll between them, especially if they are far apart. Also having to remember their name/position costs some precious brain power.</li> </ol> <p>Now, I don’t really know how most people use these filter pickers. Could be that:</p> <ol> <li>Most people just stop once they found a filter they kinda like and don’t bother trying the rest.</li> <li>Or some have a few favorites and know their name/position already.</li> <li>You could also just look at the little thumbnails. But some filters are very similar and I need to see them on the actual photo to judge.</li> </ol> <h2 id="possible-solutions">Possible solutions</h2> <p>So I was thinking about some possible improvements:</p> <h3 id="1-order-by-popularity">1. Order by popularity</h3> <p><strong>Automatically</strong> order the filters based on <strong>how often they get used</strong>. This makes filters that you use most appear at the beginning and are easier to get to. You could always keep scrolling in case you’re in the mood for something new. This would of course mess it up for people that have filters remembered by position. But not sure how many actually do that.</p> <p><img src="/img/posts/filter-2.jpg" alt="filter 2" /></p> <h3 id="2-manual-re-order">2. Manual re-order</h3> <p>Let people manually <strong>reorder the position</strong>. Could be done similar like the home screen icons on iOS (long press until they wiggle, then drag around). I would probably move my favorites to the front and also sort based on color/style.</p> <p><img src="/img/posts/filter-3.jpg" alt="filter 3" /></p> <h3 id="3-narrow-down">3. Narrow down</h3> <p>Let people <strong>temporarily toss away</strong> the filters they don’t want. This would allow you to narrow down your selection to just a few for easier comparison. Of course, all the filters would be back next time you take a new photo.</p> <p><img src="/img/posts/filter-4.gif" alt="filter 4" /></p> <p>Or probably even better (3B): Instead of throwing away the ones you don’t like (could be tedious if there are a lot of filters), you could push up <strong>only the ones you like</strong> and they would move to the right with a visual separator. It’s similar how you can <strong>pin</strong> a Chrome browser tab to separate it from the rest. Then once you scrolled to the end, you would have all your previously selected filters next to each other, waiting to be the lucky winner.</p> <h2 id="conclusion">Conclusion</h2> <p>I understand that the suggestions might make a photo app more complicated and harder to explain to a new user. But it could be more a “<strong>power user</strong>” feature that you’re not forced to use if you don’t want to. Anyways, in case I’m not the only one with this (small) problem, I hope some day we will have a better way to <strong>filter filters</strong>. Ohh.. and let me know if you’re already using an app that tackles this somehow.</p> <h2 id="update">Update</h2> <p>Thanks for all the comments. Good to see more people thinking about this. I played around a bit more with the demo, mostly after the conversation with <a href="https://twitter.com/iign">Ignacio</a> in the comments below. So here a 4th option:</p> <h3 id="4-select-and-cycle">4. Select and cycle</h3> <p>Let people <strong>select</strong> a couple filters and then <strong>cycle through them by tapping on the photo</strong>. It’s actually similar to 3B, but it keeps the UI simple by using the photo as the secondary navigation control. Here the steps how to use:</p> <ol> <li>You can tab each filter until you find one you like.</li> <li>If you tab a 2nd time on that filter, it gets selected as a “favorite”. It will move up a little to visualize it.</li> <li>You can keep trying other filters and mark more as favorites.</li> <li>Once you reached the end (or think you have enough), you can tap on the photo above the filter picker to quickly cycle through all your previously selected (favorited) filters. Now comparing different filters is really quick and easy.</li> </ol> <p><img src="/img/posts/filter-5.gif" alt="filter 5" /></p> <blockquote> <p>Try the <a href="http://simurai.com/demo/filter/">demo</a>.</p> </blockquote> <p>The implementation of the demo could still be improved. It is a bit hard to discover that you can tap the photo to cycle through your favorites. Might need some <strong>visual clue</strong> to help understand it better. Adding <strong>swipe gestures</strong> instead of tapping would also improve UX. Or to remove a filter from your favorite selection, you could just <strong>swipe down</strong> on the image. Also note that the filters are CSS based and still a bit glitchy when animating. But you should get the idea.</p> <h2 id="update-ii">Update II</h2> <p>Manuel Haring explored a <a href="http://drbl.in/omCo">similar concept</a> where you can push up filters to narrow down your selection.</p> <p><img alt="Photofilter" src="https://d13yacurqjgara.cloudfront.net/users/86752/screenshots/2002430/photofilter.gif" style="max-width: 400px;" /></p> <p>Here a larger <a href="https://dl.dropboxusercontent.com/u/95309344/find-filters-concept.mp4">video</a> that has even a third selection stage.</p> Sun, 20 Jul 2014 00:00:00 +0000 http://simurai.com/blog/2014/07/20/filtering-filters http://simurai.com/blog/2014/07/20/filtering-filters Spacing elements <p>So let’s say we have a “bar” with some items inside. Like a header or footer. Let’s also say we want those items to be spaced evenly, meaning they have the same gap everywhere. Shouldn’t be a big problem. Let’s take a look:</p> <h2 id="1-margin">1. Margin</h2> <p>We can’t just add <code class="language-plaintext highlighter-rouge">margin: 2rem</code> to the elements since there is no <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/margin_collapsing">margin collapsing</a> on the horizontal axis. And it also doesn’t work when using Flexbox. Leaving a double sized gap in between. Wishing there is something like <code class="language-plaintext highlighter-rouge">margin: 2rem collapse;</code> where you can enable/disable it optionally.</p> <p data-height="151" data-theme-id="3586" data-slug-hash="fywxI" data-default-tab="result" class="codepen">See the Pen <a href="http://codepen.io/simurai/pen/fywxI/">Spacing elements (no collapsing)</a> by simurai (<a href="http://codepen.io/simurai">@simurai</a>) on <a href="http://codepen.io">CodePen</a>.</p> <script async="" src="//codepen.io/assets/embed/ei.js"></script> <h2 id="2-pseudo-classes">2. Pseudo classes</h2> <p>Using <code class="language-plaintext highlighter-rouge">margin: 2rem 0 2rem 2rem</code> and then a pseudo class like <code class="language-plaintext highlighter-rouge">:last-child { margin-right: 2rem }</code> to add the extra margin works as long as you don’t need to hide that element with <code class="language-plaintext highlighter-rouge">display: none</code>. Maybe a rare case, but I’ve been running into this issue once in a while. Would be cool if there is something like <code class="language-plaintext highlighter-rouge">:last-displayed</code> that would ignore elements that have display:none.</p> <p data-height="151" data-theme-id="3586" data-slug-hash="cbqmK" data-default-tab="result" class="codepen">See the Pen <a href="http://codepen.io/simurai/pen/cbqmK/">Spacing elements (pseudo)</a> by simurai (<a href="http://codepen.io/simurai">@simurai</a>) on <a href="http://codepen.io">CodePen</a>.</p> <script async="" src="//codepen.io/assets/embed/ei.js"></script> <h2 id="3-margin--padding-best">3. Margin + padding (best)</h2> <p>The easiest way I think, is to add margins to all elements (like in the first example), but then also add the <strong>same value</strong> as <code class="language-plaintext highlighter-rouge">padding</code> to the parent element. Like this:</p> <div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.Header</span> <span class="p">{</span> <span class="nl">padding</span><span class="p">:</span> <span class="m">1rem</span><span class="p">;</span> <span class="p">}</span> <span class="nc">.Header-item</span> <span class="p">{</span> <span class="nl">margin</span><span class="p">:</span> <span class="m">1rem</span><span class="p">;</span> <span class="p">}</span> </code></pre></div></div> <p>That way all elements are evenly spaced and you still can use <code class="language-plaintext highlighter-rouge">display:none</code> without having to worry about breaking it. A little flaw is that you have to keep the 2 values in sync, but if you’re using a preprocessor, it can just be a single variable. Or maybe you could use REM’s to control it with <code class="language-plaintext highlighter-rouge">font-size</code> from the :root.</p> <p data-height="151" data-theme-id="3586" data-slug-hash="xsotr" data-default-tab="result" class="codepen">See the Pen <a href="http://codepen.io/simurai/pen/xsotr/">Spacing elements</a> by simurai (<a href="http://codepen.io/simurai">@simurai</a>) on <a href="http://codepen.io">CodePen</a>.</p> <script async="" src="//codepen.io/assets/embed/ei.js"></script> <h3 id="other">Other?</h3> <p>There are more ways but I’m not aware of a simple one that also let’s you use <code class="language-plaintext highlighter-rouge">display: none</code>. Let me know otherwise.</p> <ul> <li>Maybe the <a href="http://gridstylesheets.org/guides/vfl/">Visual Format Language</a> in <strong>GSS</strong>? Looks quite slick.</li> </ul> <h2 id="update">Update</h2> <p>A couple more options:</p> <ul> <li>Using Grandpa’s <a href="https://twitter.com/derSchepp/status/470809273061355520">table</a>, still need to <a href="https://twitter.com/maddesigns/status/470809480549400576">test this</a></li> <li>Using <a href="https://twitter.com/Catharsis/status/470800126911332352">calc()</a></li> <li>Using <a href="https://twitter.com/jnowland/status/470874604735442944">Adjacent selector</a></li> <li>More selector “hacks”: <a href="http://codepen.io/jnowland/pen/clbxL">1</a>, <a href="http://codepen.io/thierry/pen/KBfkv?editors=010">2</a></li> </ul> <p>Hmmm.. gotta try some. I kinda like the 3rd one. Keeps it independent from the parent and is not “too” complicated.</p> Sun, 25 May 2014 00:00:00 +0000 http://simurai.com/blog/2014/05/25/spacing-elements http://simurai.com/blog/2014/05/25/spacing-elements Styling with STRINGS <p>At this year’s <a href="http://2014.cssconf.com.au/">CSSConf</a> in Melbourne (AU) I gave a talk called “Styling with STRINGS”. The talk is about how we can use <strong>Flexbox</strong>, <strong>currentColor</strong> and __EM__s inside components to quickly style entire Web Apps straight in the browser.</p> <iframe width="100%" height="428" src="//www.youtube.com/embed/jPOBVaomzLE?list=PLZriQCloF6GDEOUPK7tlaWAtJhPW21ZDF" frameborder="0" allowfullscreen=""></iframe> <p>In case of <strong>tl:dw</strong> here some of the main points:</p> <h2 id="layout">Layout</h2> <p>When creating mobile “App” layouts, where not the whole page is scrollable, but instead only certain parts. And you have anchored areas like header/footer and a main area that should fill out the available space, then the easiest way is to use <strong>Flexbox</strong>.</p> <p><img src="/img/posts/cssconf-flexbox.gif" alt="Flexbox" /></p> <p>This lets you easily drag around components that are set as flex items and they always position nicely. Using <code class="language-plaintext highlighter-rouge">flex: 1;</code> on components makes them stretch out and fill the available space. A good use case is a search input or a title.</p> <h2 id="color">Color</h2> <p>If you don’t specify the <code class="language-plaintext highlighter-rouge">border-color</code> (initial value) it will be the same value as <code class="language-plaintext highlighter-rouge">color</code>.</p> <p><img src="/img/posts/cssconf-color1.gif" alt="initial border-color" /></p> <p>Furthermore there is a color value called <code class="language-plaintext highlighter-rouge">currentColor</code>. As the name indicates, it’s also mapped to the current color value. We can use it as <code class="language-plaintext highlighter-rouge">background-color</code> for example. Not that useful when the text should be readable, since now text and background are the same color, but for some components without text it can be quite useful. Like in the example below with the slider thumb.</p> <p><img src="/img/posts/cssconf-color2.gif" alt="currentColor" /></p> <p>If a component set should look similar to the “iOS 7” style then currentColor works great. Below all components have no color values at all and only use currentColor. This let’s us change everything by only changing the color value in the root html element.</p> <p><img src="/img/posts/cssconf-color3.gif" alt="root coloring" /></p> <h2 id="size">Size</h2> <p>In a similar way, <code class="language-plaintext highlighter-rouge">EM</code>s are mapped to <code class="language-plaintext highlighter-rouge">font-size</code>. So if we use EMs to define only the proportions of a component, we can use font-size to scale it up/down. And if we <code class="language-plaintext highlighter-rouge">inherit</code> the font-size we could also control everything at once with just a single property in the root or in groups if we go deeper down the DOM tree.</p> <p><img src="/img/posts/cssconf-size.gif" alt="EMs" /></p> <p><code class="language-plaintext highlighter-rouge">REM</code>s work the same except that they are tied to the root html element only. We could use it to control the spacing of the components by using REMs for margin/padding.</p> <p>I wrote about this in more detail in the <a href="http://simurai.com/blog/2013/07/03/sizing-components">Sizing (Web) Components</a> post.</p> <h2 id="all-together">All together</h2> <p>Now if we combine this all and test it in an example application, we can easily design many variations right from the DevTools/inspector in a quick and easy way.</p> <p><img src="/img/posts/cssconf-gallery.jpg" alt="Gallery" /></p> <p>Feel free to play around with the <a href="http://simurai.github.io/cssconf-app">CSSConf App</a> yourself or check out the source on <a href="https://github.com/simurai/cssconf-app">GitHub</a>.</p> <h2 id="how-to-save">How to save?</h2> <p>You might wonder how you can save the changes made in the DevTools/inspector without having to manually copy them over into your CSS file. In Chrome there is a feature called <strong>Workspaces</strong>. It let’s you map a URL to a local folder. Once that is setup, all CSS changes will automatically be saved to your local disc. Here a post that explains how to setup <a href="http://www.html5rocks.com/en/tutorials/developertools/revolutions2013/#toc-workspaces">Workspaces</a>. It’s advised to use version control like Git, so that you can always discard all changes if you went too far and wanna start over.</p> <h2 id="conclusion">Conclusion</h2> <p>Admittedly it is somewhat in between of being useful for production and just a “hack”. Especially the <code class="language-plaintext highlighter-rouge">currentColor</code>. But the main point of the talk is best told by this quote:</p> <blockquote> <p>“Creators need an immediate connection” — Bret Victor</p> </blockquote> <p>The examples I used are just the closest I could get using CSS alone and still keep code clean. I hope we keep that principle alive and improve on it.</p> <hr /> <p>ps. Artist of the puppet master illustration: Unknown.</p> <p>pss. Here all the other <a href="http://2014.cssconf.com.au/news/videos/">videos</a> from CSSConf.</p> Sun, 04 May 2014 00:00:00 +0000 http://simurai.com/blog/2014/05/04/cssconf http://simurai.com/blog/2014/05/04/cssconf Moving to Jekyll <p>I haven’t redesigned my site for years, can’t even remember exactly. Also, haven’t been posting for a while. So as a New Year’s resolution I redid my site using <a href="http://jekyllrb.com/">Jekyll</a> and am hosting it as a <a href="https://github.com/simurai/simurai.github.io">GitHub page</a>.</p> <p><img class="img--25" src="/img/posts/jekyll.jpg" alt="jekyll logo" /></p> Sun, 02 Feb 2014 00:00:00 +0000 http://simurai.com/news/2014/02/02/jekyll http://simurai.com/news/2014/02/02/jekyll A BEM syntax with UX in mind <p>At some point, while working on the MontageJS framework, the question came up what CSS naming convention we should start using. After a <a href="https://github.com/montagejs/montage/issues/795">long discussion</a> we settled on using the <a href="http://bem.info/method/definitions/">BEM methodology</a>, but changed the syntax a bit. To keep this post short, I won’t go into detail why using BEM is a good idea, but rather explain why we chose a different syntax. Here some examples:</p> <div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.digit-Progress</span> <span class="c">/* org-Component */</span> <span class="nc">.digit-Progress-bar</span> <span class="c">/* org-Component-childElement */</span> <span class="nc">.digit-Progress--small</span> <span class="c">/* org-Component--variation */</span> </code></pre></div></div> <blockquote> <p>Note: The <code class="language-plaintext highlighter-rouge">org-</code> (digit-) prefix is used as a name-space so it wouldn’t conflict with other packages/libraries/frameworks.</p> </blockquote> <p>Now let’s take a look at the reasons for choosing such a syntax.</p> <h3 id="hyphens--">Hyphens (-)</h3> <p>The main reason why we’re using a hyphen (<code class="language-plaintext highlighter-rouge">-</code>) instead of underscores (<code class="language-plaintext highlighter-rouge">_</code>), has to do with the fact that their behavior is different when <strong>double-clicking</strong> to select text. Try for yourself:</p> <div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">component__element</span> <span class="c">/* underscores */</span> <span class="nt">component-element</span> <span class="c">/* hyphen */</span> </code></pre></div></div> <p><img src="/img/posts/BEM-1.gif" alt="naming-conventions-1" /></p> <p>See how when you’re using underscores it selects the part before and after, in this case the whole <code class="language-plaintext highlighter-rouge">component__element</code>. But with hyphens it let’s you select only the part you double-clicked. <code class="language-plaintext highlighter-rouge">component</code> <strong>OR</strong> <code class="language-plaintext highlighter-rouge">element</code>. This let’s you quickly edit only the parts you want:</p> <p><img src="/img/posts/BEM-2.gif" alt="naming-conventions-2" /></p> <h3 id="camelcase">camelCase</h3> <p>Now, what if the component or child element consists of multiple words? We could use underscores like <code class="language-plaintext highlighter-rouge">component_name-element_name</code>. It would still be double-clickable, but readability suffers since it’s harder to see what belongs together. Better to use <strong>camelCase</strong> which groups each part visually: <code class="language-plaintext highlighter-rouge">componentName-elementName</code>.</p> <h3 id="maincomponent">MainComponent</h3> <p>OK, I think we’re getting closer. As a last rule, for the “main” component we use <code class="language-plaintext highlighter-rouge">PascalCase</code>. The reason for it is to add <strong>emphasis</strong> and make it easier to distinguish the main component from a child element. Also when using a namespace, the component moves to the second position, which makes it even more important to have it stick out: <code class="language-plaintext highlighter-rouge">org-Component-childElement</code></p> <h3 id="variation">–variation</h3> <p>We kept the more commonly used double hyphens (–) for <strong>variations</strong>. <code class="language-plaintext highlighter-rouge">digit-Progress--small</code>. It makes sense, because it pulls the variation (–small) visually more apart and makes it look like it’s something “different” than the default component.</p> <hr /> <p>So that’s about it. For more details about this naming convention, take a look at the <a href="https://github.com/suitcss/suit/blob/master/doc/naming-conventions.md">SUIT framework</a>, which also started to use the same syntax and documented it really well.</p> <p>In the end, whatever <a href="http://blog.kaelig.fr/post/48196348743/fifty-shades-of-bem">Shade of BEM</a> you choose to cook with probably depends on your personal taste, but thinking about a great UX by improving usability and readability won’t hurt either.</p> Thu, 24 Oct 2013 00:00:00 +0000 http://simurai.com/blog/2013/10/24/BEM-syntax-with-ux-in-mind http://simurai.com/blog/2013/10/24/BEM-syntax-with-ux-in-mind