Today I Learned

A Hashrocket project

41 posts about #html-css

Make A Block Of Text Respect A New Line

Generally when we fill a div tag full of text, it will display it one long strand irrespective of any line breaks that are included. This is a great default, but not necessarily what we want when we are displaying text from another source, such as our users.

We can convince a block of text to respect new lines by adding a couple CSS properties.

.multiline-text {
  word-wrap: break-word;
  white-space: pre-line;
}

The first rule, word-wrap: break-word, ensures that long lines of text uninterrupted by new lines respect the boundaries of our wrapping element. The second rule, white-space: pre-line, handles squashing of extra white space and respecting of new lines.

See a working example here.

The Outline Property 🖼

Today I learned about the CSS outline property.

Outlines are like borders, except they never take up space, because they’re drawn outside of an element’s content.

Some browsers have a default outline style for interactive elements (like buttons) on focus. This was how I came to learn about the property, because that style clashed visually with an element I was building.

Remove such an outline with either of these settings:

button:focus {
  outline: 0;
  outline: none;
}

Note that if an element can be interacted with, a11y best practices require a visible focus indicator. Provide obvious focus styling if the default focus style is removed.

Animate Smoothly Between Two Background Colors

CSS animations allow you to set up simple rules that the rendering engine can then apply to create smooth transitions between style states.

To smoothly transition between two background colors, we can create a keyframes at-rule with a fitting name (e.g. pulse).

@keyframes pulse {
  0% {
    background-color: red;
  }
  50% {
    background-color: blue;
  }
  100% {
    background-color: red;
  }
}

Over the course of a single animation, this set of rules will start the background color at red, transition to blue 50% of the way through, and then back to red again.

We can then apply this animation within any of our CSS class definitions.

.square1 {
  animation: pulse 2s infinite;
  width: 100px;
  height: 100px;
}

Anything with a class of square1 will have a width and height of 100px as well as a pulsing background color.

Add Fab Icons To Your Site With FontAwesome 5

Check out the latest version of FontAwesome.

Version 5 has been re-written and re-designed completely from scratch.

One part of the rewrite is that brand icons have been organized into their own collection. Whether you are using the full suite or just the brands bundle, you’ll be referencing these icons with the fab class name.

<i class="fab fa-react" />

This will give you a React icon.

Check out all the different brand icons here.

Pin item to bottom of container

In laying out the items of a container, I want an item to be pinned to the bottom no matter the size of the other content. I can do that with a mix of flex and margin: auto.

.container {
  display: flex;
  flex-flow: column;
}

.footer {
  margin-top: auto;
}

I had previously thought that flex box was more contained and wouldn’t change the behaviour of properties like margin: auto but it does!

Check out my codepen here.

H/T Vidal Ekechuckwu

Apply Styles To the Last Child Of A Specific Type

The :last-child pseudo-class is a way of specifying styling that will only be applied to an element if it is the last child among its siblings. What if we have elements that are declared amongst elements of another type? This can complicate that styling.

The styling

span:last-child {
  color: red;
}

won’t take effect on our last span here

<div>
  <span>One</span>
  <span>Two</span>
  <span>Three</span>
  <div>Something unrelated</div>
</div>

because amongst its siblings it isn’t the last.

One way of getting around this is with the :last-of-type pseudo-class.

span:last-of-type {
  color: red;
}

See a live example here.

Clip images in html with `clip-path`

You may have some images that have some annoying artifacts around the border, or maybe you just want an image to be a funky shape for design purposes. If so, then clip-path is the css property for you.

Check out this diamond shaped image from the mdn docs:

clip-path: polygon(50% 0, 100% 50%, 50% 100%, 0 50%);

There are 4 functions, circle, ellipse, polygon, and inset, amongst a number of interesting options, some of which work in your browser currently, some of which may not.

Creating a vector for your specific shape might sound rough, but firefox has a built-in clip-path tool that can help you set it correctly in the browser.

Rearrange items with `grid-template-areas`

You can arrange items with the css-grid property grid-template-areas without changing the structure of your html.

Here I have basic strategy for a 2x2 grid with item one in the upper left corner and item four in the lower right.

.container {
  display: grid;
  grid-template-columns: 1fr;
  grid-template-rows: 1fr;
  grid-tempate-areas: 
    "one two"
    "three four";
}

.one { grid-area: one }
.two { grid-area: two }
.three { grid-area: three }
.four { grid-area: four }

I can rearrange my items just by changing the grid-template-areas property:

.container {
  grid-template-areas:
    "four two"
    "three one";
}

Now, item four is in the upper left corner, and item one is in the lower right.

A complete example is up at CodePen

Alpha channel in hex colors #RRGGBBAA

In the past if I’ve needed to give a hex color an opactiy I would use the opacity attribute, like this:

div {
  background-color: #cecece;
  opacity: 0.5;
}

But as of Chrome 62/Firefox 49/CSS Color Module Level 4 you can now include the alpha channel information into the hex code:

div {
  background-color: #cecece88;
}

And if you are using the shortened version of the hex color it looks like this:

div { 
  background-color: #ccc8;
}

Check out the MDN Docs

Span a grid item across the entire css grid

When using css grid you might want an item to span item to span across the entire grid even when that grid has many columns.

Grid with many columns looks like this:

.grid {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
}

You could certainly just use grid-column: span 5 but if the number of columns changes then you aren’t going across the entire screen. To span a grid item across the entire css grid regardless of number of columns use the / operator and the index of the last column -1:

.item {
  grid-column: 1 / -1;
}

Preventing access to `Window.opener`

When you open a link in a new tab with target="_blank" like so:

<a target="_blank" href="http://some.link">Somewhere</a>

Then the page that you open has access to the original page through Window.opener. Depending on your case you may not want this. Actually I can’t think of a case where you do want the new tab to refer back to the opening tab.

To prevent Window.opener access use rel="noopener":

<a target="_blank" href="http://some.link" rel="noopener">Somelink</a>

At this moment, this is not available in IE or Edge, check out the caniuse site.

H/T Dillon Hafer

flex-flow for shorter flex declarations

flex-flow is a css property that allows you to specify both flex-direction and flex-wrap in one property. In css parlance this is a shorthand property and like all shorthand properties the values are order agnostic when possible.

It will provide minimal efficiency gains but you can just avoid writing flex-direction altogether. When you need to specify a direction just type:

ul { 
  display: flex;
  flex-flow: row;
}

And then its easy to tack on a wrap when you determine it is necessary:

ul {
  display: flex;
  flex-flow: row wrap;
}

Native CSS Variables

CSS variables are normally associated with the pre-processor languages like SASS. But css has its own native variables as well. Declare them like so:

element { 
  --black-grey: #111111;
}

And then use them with the var function like this:

element { 
  background-color: var(--black-grey);
}

In the above example if --black-grey is not set then the background-color will fallback to the inherited value. You can provide a default value for the variable if you anticipate it may not be set:

element {
  background-color: var(--black-grey, black);
}

Variables behave just like any other inherited or cascading properties and if you’d like them available for entire stylesheets then you would need to declare them in :root.

:root {
  --one-fathom: 16rem;
}

This css feature is safe to use everywhere but IE, but it is only recently safe. Firefox enabled this feature by default in version 56 released in Sept 2017.

You can read about them in the Mozilla Docs or the original W3C editor’s draft.

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)