Today I Learned

A Hashrocket project

27 posts about #html-css

Parameterized SCSS Mixins

A mixin can be made to be much more versatile by parameterizing it. If you need variations of a block of CSS, then move the parts that vary out into parameters to the mixin.

@mixin navigation($background-color, $color, $link-color) {
  nav {
    display: flex;
    justify-content: space-around;
    background-color: $background-color;
    color: $color;

    ul {
      list-style: none;

      li a {
        text-decoration: none;
        color: $link-color;
      }
    }
  }
}

div.base-nav {
  @include navgation(#fff, #444, #222);
}

div.admin-nav {
  @include navgation(#000, #fff, #ddd);
}

The mixin can now easily be used to customize different segments of your app’s styling.

Dry Up SCSS With Mixins

If you have a similar chunk of styling that is being duplicated across your CSS, you’d probably like to dry it up to reduce the pain of maintaining it. Mixins provide one way of dealing with this problem.

First, declare a named mixin of the styles that you are trying to dry up.

@mixin navigation {
  nav {
    display: flex;
    justify-content: space-around;

    ul {
      list-style: none;

      li a {
        text-decoration: none;
      }
    }
  }
}

Then, this mixin can be included wherever it is needed.

div.base-nav {
  @include navigation;
  background-color: #fff;
  color: #444;

  nav ul {
    li a:hover {
      color: #222;
    }
  }
}

div.admin-nav {
  @include navigation;
  background-color: #000;
  color: #fff;

  nav ul {
    li a:hover {
      color: #ddd;
    }
  }
}

Any subsequent changes to the core navigation styling only need to be made in one place, the mixin.

source

h/t Dorian Karter

Animating polygon must have same number of points

You can show an SVG polygon changing shape with SVG’s animate tag.

<polygon points="100,100 0,100 0,0">
  <animate
    to="50,50 0,50 0,0"
    from="100,100 0,100 0,0"
    dur="10s"
    attributeName="points"
  />
</polygon>

However, you can not animate a shape change to a different number of points. For instance if you have three points in the to attribute and four points in the from attribute, then nothing will happen.

Recently, I wanted to animate a change from a 4 pointed polygon to a 5 pointed polygon. In this case, I included an extra point in the 4 pointed polygon that was a duplicate of an existing point and right next to that same duplicated point. When changing shape to a 5 pointed polygon, the previously duplicated point moved out from that spot to its new spot and the polygon adjusted accordingly and pleasingly.

Turn Off HTML5 Form Validations

HTML5 added a variety of input types such as date, email, and tel (telephone number). These make entering certain kinds of information easier by providing tools such as a datepickers, range sliders, and optimized keyboards on mobile devices.

These input types also introduce custom validations on some browsers, which are useful, but can potentially clash with your application’s look and feel.

To keep the input type, but disable the validations, add novalidate to your form tag:

<form novalidate />

h/t Dillon Hafer

docs

Lighten And Darken With CSS Brightness Filter

CSS has a filter property that can be used with a variety of filter functions. One of them is the brightness() filter. By feeding a percentage less than 100% to brightness(), the target element will be made darker. Inversely, feeding a percentage greater than 100% to brightness() will make the element brighter.

.brighter-span {
  filter: brightness(150%);
}

.darker-span {
  filter: brightness(50%);
}

brighter, regular, and darker spans

See this CSS Tricks Article on the filter property for more details. Check out the browser support story here.

Hack to size the container of a background image

An element that contains a background image cannot have its height and width derived from that background image. An element can have a height and width that is determined by the size of a child element however. Combine the two to ensure that the container of the background image has the height and width of the image itself.

<div style="background-image: url('http://example.com/image.png')">
    <img src="http://example.com/image.png">
</div>

`border-collapse` to collapse borders

There are two settings for the css property border-collapse, separate and collapse. Table cells and the table itself can both have borders. If the value separate is set, then each cell has its own border, with the space in between the borders governed by the border-spacing property.

If collapse is set, then the table cells and the surrounding table will share the borders surrounding them.

Refresh A Twitter Summary Card Image

Twitter provides a feature called summary card images: if you’ve ever seen a tweet with a rectangular image included, that’s it. We can specify this image via HTML meta tags. Most tweets from the @hashrocketil follow this pattern.

Changing the image is tricky, however, because Twitter caches summary cards for an unknown amount of time (I’ve read one week). Which means past and future Tweets could include an outdated image for a while.

One solution is to use Twitter’s card validator on your site. Running the site it through the validator seems to refresh the cache for your summary cards.

CSS Variables

CSS3 supports native variables that are assigned with the following syntax:

html {
  --foo-color: #FF0000;
  --bar-color: #00FF00;
}

Note the -- that precedes the variable’s name. Now, the <html> element and all its descendants will be able to access the variables with the following syntax.

a {
  color: var(--foo-color);
}

button {
  background: var(--bar-color);
}

CSS uses the var function to look up variables.

You don’t have to assign the variable to the <html> tag. It can be assigned to any element or selector’s style block. Just remember, only that element and its children will have access to the variable ;-)

Futhermore, you can access the variables in Chrome’s DevTool/Element Inspector!

NOTE: This feature is not supported at all in Internet Explorer and only has partial support in Microsoft Edge 15, the most recent Edge at this time of writing. Opera Mini users are out of luck as well :-(

Browser Support Chart

rel attribute for performance and security

The rel attribute on HTML links need to be set to noopener if you’re using target=_blank in your links, otherwise the new tab contains a reference to the other tab’s window object, and can redirect, manipulate dom, etc.

Read more and see a demo here: https://mathiasbynens.github.io/rel-noopener

There are also some performance benefits: https://jakearchibald.com/2016/performance-benefits-of-rel-noopener/

Spellcheck Attribute

Have you ever noticed formatting like this in a text field?

The browser knows that ‘Today’ and ‘Learned’ are misspelled… but how?

The answer is the spellcheck attribute. Set it to true to enable the spellcheck magic. Right click each word for suggestions, dictionaries, etc. (Chrome).

Spellcheck is enabled by default on Chrome, but you will have to set it explicitly on some or all versions of Firefox and IE. Learn more here:

http://caniuse.com/#feat=spellcheck-attribute

Create a Placeholder for Content Editable Divs

When you have a content editable div. Add an data attribute. We’re going to use placeholder:

<div contenteditable="true" data-placeholder="(untitled)" class="title">
</div>

Then in your css, use a few pseudo classes to make it behave like a placholder:

.title:empty:not(:focus):before {
  content: attr(data-placeholder)
}

Very cool! I (for whatever reason) never knew about :empty, :not, attr() or chaining multiple pseudo classes. Learned a lot in this little snippet :)

h/t @alejandroRINC0N

Break long strings nicely with <wbr>

Are super-long strings (typically URLs) breaking out of an otherwise narrow column of text in your design? Sprinkle in some <wbr> tags; they don’t take up any space, but provide the browser with safe places to break the string to a new line.

For example, this super-long URL will look normal, but if it’s in a narrow area it’ll linebreak at any of the <wbr> points:

<a href="https://basecamp.com/188854/projects/1034065/messages/6033885">
  https://basecamp.co
  <wbr>
  m/188854/projects/1
  <wbr>
  034065/messages/603
  <wbr>
  3885
</a>

Learn all about the <wbr> at MDN.

Frontmatter Date Affects Build

Middleman is an excellent choice for blogging. Combined with Frontmatter, we can do many things.

Today I learned that if you include a future date key in your Frontmatter, the file in question will be excluded from the build.

And so, today, this file would not be built with middleman build:

<!-- source/episodes/1/first_episode.html.markdown -->
---
date: 06-21-2016
---

This makes sense, but it was not intuitive to me and took some troubleshooting.

The `<picture>` element is here to stay!

Safari 9.1 has officially added support for the <picture> element, allowing you to specify multiple image resources per viewport size. Now that Chrome and Safari both support it, go nuts (as long as you don’t need to support IE).

<picture>
    <source media="(min-width: 1000px)" srcset="picture_large.jpg">
    <source media="(min-width: 500px)" srcset="picture_small.jpg">
    <img src="picture_default.jpg">
</picture>

Read more about it in the release notes!

Max out your `vw` with Sass

A pretty big downside to vw units is that they are relative to the viewport width, regardless of the maximum width of your site itself. So if the user fullscreens your site on a big monitor, your vws will be huge while the rest of your site stops growing at some reasonable width. Here’s a handy Sass mixin to address that problem.

@mixin max-vw($attr, $value) {
  #{$attr}: #{$value}vw;
  @media screen and (min-width: 1400px) {
    #{$attr}: ($value/100) * 1400px;
}

Basically, since 1 vw is 1% of the viewport width, at a certain max breakpoint, we use an equivalent percentage of the max site width instead.

For example, this will assign a font-size of 10vw, but after the viewport enlarges past 1400px, the font-size will then set to a static 140px (10% of 1400px):

.foo {
  @include max-vw(font-size, 10)
}

HTML in Markdown

Today I learned that you can add raw HTML directly into a Markdown file.

This realization came when trying to include an image in a blog post. I started out by linking to the image with standard Markdown syntax:

![Image](https://s3.amazonaws.com/jake/image.png)

But later realized I wanted to include a responsive Bootstrap class on the image, which I did with raw HTML:

<img src="https://s3.amazonaws.com/jake/image.png" class="img-responsive" alt="Image">

It’s pretty cool that you can do both— Markdown syntax gets processed into HTML, but raw HTML can be used as well.

Animate with Transforms for Great CPU Success

I’m currently animating a bunch of clouds across a sky, for a thing, doesn’t matter. I was previously animating with:

@keyframes cloud {
  0% {
    margin-left: 100vw;
  }
  100% {
    margin-left: -30vw;
  }
}

10 clouds ate about 70-75% of my CPU. When I switched to transform instead, my CPU usage dropped to about 20%:

@keyframes cloud {
  0% {
    transform: translateX(100vw);
  }
  100% {
    transform: translateX(-30vw);
  }
}

So: animate with transforms whenever possible to save the planet.

Protocol-relative URLs are now discouraged

For a long time, I’ve used protocol-relative URLs as a way to serve assets from a page using the same protocol (i.e. http or https) as the parent page. They look like this:

<img src="//google.com/path/to/image.jpg"/>

But now that SSL is encouraged everywhere on the web, one should always use https when an asset supports it.

<img src="https://google.com/path/to/image.jpg"/>

According to Paul Irish, It’s always safe to request HTTPS assets even if your site is on HTTP, however the reverse is not true.

Smarter CSS positioning with calc()

Let’s talk a specific use case: if you’re looking to position something a fixed amount from the bottom edge of an area, you’ll end up with something like this:

.foo {
  position: absolute;
  top: 100%;
}

… but if you want the element to be offset a fixed amount from the bottom edge, the standard methodology used to be to just add some margin:

.foo {
  position: absolute;
  top: 100%;
  margin-top: 10px;
}

However, with calc(), you can just throw a fixed amount onto your percentage:

.foo {
  top: calc(100% + 5px)
}

There are countless other uses, but for me that’s the one that comes up the most, so there you go. As always, check caniuse.com for browser caveats (you’re basically safe everywhere except <IE10).

VW FTW

If you haven’t used CSS viewport units like vw and vh yet, you’re missing out on some really fun ways to solve responsive problems. A vw and a vh are equal to 1% of the viewport width and height, respectively.

  • use vw for padding to scale your padding responsively without having to use @media breakpoints
  • set a font-size in vw to allow fonts to scale with the viewport (the TODAY I LEARNED page heading is set using vw)
  • use vw for box-shadow to let your box-shadows scale down with the page (also a feature of the TIL site)

For more sweet viewport unit tricks, check out Rye Mason’s post on the Hashrocket blog.

Generating subclasses with Sass Maps

Say you have a set of colors that correspond to class names:

$category-colors: (
  "bananas": "yellow",
  "oranges": "orange",
  "blue-milk": "cyan",
  "cabbage": "lime",
  "sour-warheads": "magenta"
);

And sometimes those class names recolor a background, but sometimes they might override something else, like a border or text color. Try this mixin on for size:

@mixin category-colors($attr:color)
  @each $class, $color in $category-colors
    &.#{$class}
      #{$attr}: #{$color}

So this call will output subclasses of .widget.bananas, etc., each with the appropriate text color …

.widget
  @include category-colors

And this one will output subclasses with the appropriate background color (or whatever other attribute you’d like).

.widget
  @include category-colors(background-color)