Front End Web Development

The Shapes of CSS

Css Tricks - Mon, 10/01/2018 - 4:05am

CSS is capable of making all sorts of shapes. Squares and rectangles are easy, as they are the natural shapes of the web. Add a width and height and you have the exact size rectangle you need. Add border-radius and you can round that shape, and enough of it you can turn those rectangles into circles and ovals.

We also get the ::before and ::after psuedo elements in CSS, which give us the potential of two more shapes we can add to the original element. By getting clever with positioning, transforming, and many other tricks, we can make lots of shapes in CSS with only a single HTML element.

Square #square { width: 100px; height: 100px; background: red; } Rectangle #rectangle { width: 200px; height: 100px; background: red; } Circle #circle { width: 100px; height: 100px; background: red; border-radius: 50% } Oval #oval { width: 200px; height: 100px; background: red; border-radius: 100px / 50px; } Triangle Up #triangle-up { width: 0; height: 0; border-left: 50px solid transparent; border-right: 50px solid transparent; border-bottom: 100px solid red; } Triangle Down #triangle-down { width: 0; height: 0; border-left: 50px solid transparent; border-right: 50px solid transparent; border-top: 100px solid red; } Triangle Left #triangle-left { width: 0; height: 0; border-top: 50px solid transparent; border-right: 100px solid red; border-bottom: 50px solid transparent; } Triangle Right #triangle-right { width: 0; height: 0; border-top: 50px solid transparent; border-left: 100px solid red; border-bottom: 50px solid transparent; } Triangle Top Left #triangle-topleft { width: 0; height: 0; border-top: 100px solid red; border-right: 100px solid transparent; } Triangle Top Right #triangle-topright { width: 0; height: 0; border-top: 100px solid red; border-left: 100px solid transparent; } Triangle Bottom Left #triangle-bottomleft { width: 0; height: 0; border-bottom: 100px solid red; border-right: 100px solid transparent; } Triangle Bottom Right #triangle-bottomright { width: 0; height: 0; border-bottom: 100px solid red; border-left: 100px solid transparent; } Curved Tail Arrow via Ando Razafimandimby #curvedarrow { position: relative; width: 0; height: 0; border-top: 9px solid transparent; border-right: 9px solid red; transform: rotate(10deg); } #curvedarrow:after { content: ""; position: absolute; border: 0 solid transparent; border-top: 3px solid red; border-radius: 20px 0 0 0; top: -12px; left: -9px; width: 12px; height: 12px; transform: rotate(45deg); } Trapezoid #trapezoid { border-bottom: 100px solid red; border-left: 25px solid transparent; border-right: 25px solid transparent; height: 0; width: 100px; } Parallelogram #parallelogram { width: 150px; height: 100px; transform: skew(20deg); background: red; } Star (6-points) #star-six { width: 0; height: 0; border-left: 50px solid transparent; border-right: 50px solid transparent; border-bottom: 100px solid red; position: relative; } #star-six:after { width: 0; height: 0; border-left: 50px solid transparent; border-right: 50px solid transparent; border-top: 100px solid red; position: absolute; content: ""; top: 30px; left: -50px; } Star (5-points) via Kit MacAllister #star-five { margin: 50px 0; position: relative; display: block; color: red; width: 0px; height: 0px; border-right: 100px solid transparent; border-bottom: 70px solid red; border-left: 100px solid transparent; transform: rotate(35deg); } #star-five:before { border-bottom: 80px solid red; border-left: 30px solid transparent; border-right: 30px solid transparent; position: absolute; height: 0; width: 0; top: -45px; left: -65px; display: block; content: ''; transform: rotate(-35deg); } #star-five:after { position: absolute; display: block; color: red; top: 3px; left: -105px; width: 0px; height: 0px; border-right: 100px solid transparent; border-bottom: 70px solid red; border-left: 100px solid transparent; transform: rotate(-70deg); content: ''; } Pentagon #pentagon { position: relative; width: 54px; box-sizing: content-box; border-width: 50px 18px 0; border-style: solid; border-color: red transparent; } #pentagon:before { content: ""; position: absolute; height: 0; width: 0; top: -85px; left: -18px; border-width: 0 45px 35px; border-style: solid; border-color: transparent transparent red; } Hexagon #hexagon { width: 100px; height: 55px; background: red; position: relative; } #hexagon:before { content: ""; position: absolute; top: -25px; left: 0; width: 0; height: 0; border-left: 50px solid transparent; border-right: 50px solid transparent; border-bottom: 25px solid red; } #hexagon:after { content: ""; position: absolute; bottom: -25px; left: 0; width: 0; height: 0; border-left: 50px solid transparent; border-right: 50px solid transparent; border-top: 25px solid red; } Octagon #octagon { width: 100px; height: 100px; background: red; position: relative; } #octagon:before { content: ""; width: 100px; height: 0; position: absolute; top: 0; left: 0; border-bottom: 29px solid red; border-left: 29px solid #eee; border-right: 29px solid #eee; } #octagon:after { content: ""; width: 100px; height: 0; position: absolute; bottom: 0; left: 0; border-top: 29px solid red; border-left: 29px solid #eee; border-right: 29px solid #eee; } Heart via Nicolas Gallagher #heart { position: relative; width: 100px; height: 90px; } #heart:before, #heart:after { position: absolute; content: ""; left: 50px; top: 0; width: 50px; height: 80px; background: red; border-radius: 50px 50px 0 0; transform: rotate(-45deg); transform-origin: 0 100%; } #heart:after { left: 0; transform: rotate(45deg); transform-origin: 100% 100%; } Infinity via Nicolas Gallagher #infinity { position: relative; width: 212px; height: 100px; box-sizing: content-box; } #infinity:before, #infinity:after { content: ""; box-sizing: content-box; position: absolute; top: 0; left: 0; width: 60px; height: 60px; border: 20px solid red; border-radius: 50px 50px 0 50px; transform: rotate(-45deg); } #infinity:after { left: auto; right: 0; border-radius: 50px 50px 50px 0; transform: rotate(45deg); } Diamond Square via Joseph Silber #diamond { width: 0; height: 0; border: 50px solid transparent; border-bottom-color: red; position: relative; top: -50px; } #diamond:after { content: ''; position: absolute; left: -50px; top: 50px; width: 0; height: 0; border: 50px solid transparent; border-top-color: red; } Diamond Shield via Joseph Silber #diamond-shield { width: 0; height: 0; border: 50px solid transparent; border-bottom: 20px solid red; position: relative; top: -50px; } #diamond-shield:after { content: ''; position: absolute; left: -50px; top: 20px; width: 0; height: 0; border: 50px solid transparent; border-top: 70px solid red; } Diamond Narrow via Joseph Silber #diamond-narrow { width: 0; height: 0; border: 50px solid transparent; border-bottom: 70px solid red; position: relative; top: -50px; } #diamond-narrow:after { content: ''; position: absolute; left: -50px; top: 70px; width: 0; height: 0; border: 50px solid transparent; border-top: 70px solid red; } Cut Diamond via Alexander Futekov #cut-diamond { border-style: solid; border-color: transparent transparent red transparent; border-width: 0 25px 25px 25px; height: 0; width: 50px; box-sizing: content-box; position: relative; margin: 20px 0 50px 0; } #cut-diamond:after { content: ""; position: absolute; top: 25px; left: -25px; width: 0; height: 0; border-style: solid; border-color: red transparent transparent transparent; border-width: 70px 50px 0 50px; } Egg #egg { display: block; width: 126px; height: 180px; background-color: red; border-radius: 50% 50% 50% 50% / 60% 60% 40% 40%; } Pac-Man #pacman { width: 0px; height: 0px; border-right: 60px solid transparent; border-top: 60px solid red; border-left: 60px solid red; border-bottom: 60px solid red; border-top-left-radius: 60px; border-top-right-radius: 60px; border-bottom-left-radius: 60px; border-bottom-right-radius: 60px; } Talk Bubble #talkbubble { width: 120px; height: 80px; background: red; position: relative; -moz-border-radius: 10px; -webkit-border-radius: 10px; border-radius: 10px; } #talkbubble:before { content: ""; position: absolute; right: 100%; top: 26px; width: 0; height: 0; border-top: 13px solid transparent; border-right: 26px solid red; border-bottom: 13px solid transparent; } 12 Point Burst via Alan Johnson #burst-12 { background: red; width: 80px; height: 80px; position: relative; text-align: center; } #burst-12:before, #burst-12:after { content: ""; position: absolute; top: 0; left: 0; height: 80px; width: 80px; background: red; } #burst-12:before { transform: rotate(30deg); } #burst-12:after { transform: rotate(60deg); } 8 Point Burst via Alan Johnson #burst-8 { background: red; width: 80px; height: 80px; position: relative; text-align: center; transform: rotate(20deg); } #burst-8:before { content: ""; position: absolute; top: 0; left: 0; height: 80px; width: 80px; background: red; transform: rotate(135deg); } Yin Yang via Alexander Futekov #yin-yang { width: 96px; box-sizing: content-box; height: 48px; background: #eee; border-color: red; border-style: solid; border-width: 2px 2px 50px 2px; border-radius: 100%; position: relative; } #yin-yang:before { content: ""; position: absolute; top: 50%; left: 0; background: #eee; border: 18px solid red; border-radius: 100%; width: 12px; height: 12px; box-sizing: content-box; } #yin-yang:after { content: ""; position: absolute; top: 50%; left: 50%; background: red; border: 18px solid #eee; border-radius: 100%; width: 12px; height: 12px; box-sizing: content-box; } Badge Ribbon via Catalin Rosu #badge-ribbon { position: relative; background: red; height: 100px; width: 100px; border-radius: 50px; } #badge-ribbon:before, #badge-ribbon:after { content: ''; position: absolute; border-bottom: 70px solid red; border-left: 40px solid transparent; border-right: 40px solid transparent; top: 70px; left: -10px; transform: rotate(-140deg); } #badge-ribbon:after { left: auto; right: -10px; transform: rotate(140deg); } Space Invader via Vlad Zinculescu #space-invader { box-shadow: 0 0 0 1em red, 0 1em 0 1em red, -2.5em 1.5em 0 .5em red, 2.5em 1.5em 0 .5em red, -3em -3em 0 0 red, 3em -3em 0 0 red, -2em -2em 0 0 red, 2em -2em 0 0 red, -3em -1em 0 0 red, -2em -1em 0 0 red, 2em -1em 0 0 red, 3em -1em 0 0 red, -4em 0 0 0 red, -3em 0 0 0 red, 3em 0 0 0 red, 4em 0 0 0 red, -5em 1em 0 0 red, -4em 1em 0 0 red, 4em 1em 0 0 red, 5em 1em 0 0 red, -5em 2em 0 0 red, 5em 2em 0 0 red, -5em 3em 0 0 red, -3em 3em 0 0 red, 3em 3em 0 0 red, 5em 3em 0 0 red, -2em 4em 0 0 red, -1em 4em 0 0 red, 1em 4em 0 0 red, 2em 4em 0 0 red; background: red; width: 1em; height: 1em; overflow: hidden; margin: 50px 0 70px 65px; } TV Screen #tv { position: relative; width: 200px; height: 150px; margin: 20px 0; background: red; border-radius: 50% / 10%; color: white; text-align: center; text-indent: .1em; } #tv:before { content: ''; position: absolute; top: 10%; bottom: 10%; right: -5%; left: -5%; background: inherit; border-radius: 5% / 50%; } Chevron via Anthony Ticknor #chevron { position: relative; text-align: center; padding: 12px; margin-bottom: 6px; height: 60px; width: 200px; } #chevron:before { content: ''; position: absolute; top: 0; left: 0; height: 100%; width: 51%; background: red; transform: skew(0deg, 6deg); } #chevron:after { content: ''; position: absolute; top: 0; right: 0; height: 100%; width: 50%; background: red; transform: skew(0deg, -6deg); } Magnifying Glass #magnifying-glass { font-size: 10em; display: inline-block; width: 0.4em; box-sizing: content-box; height: 0.4em; border: 0.1em solid red; position: relative; border-radius: 0.35em; } #magnifying-glass:before { content: ""; display: inline-block; position: absolute; right: -0.25em; bottom: -0.1em; border-width: 0; background: red; width: 0.35em; height: 0.08em; transform: rotate(45deg); } Facebook Icon via Nathan Swartz #facebook-icon { background: red; text-indent: -999em; width: 100px; height: 110px; box-sizing: content-box; border-radius: 5px; position: relative; overflow: hidden; border: 15px solid red; border-bottom: 0; } #facebook-icon:before { content: "/20"; position: absolute; background: red; width: 40px; height: 90px; bottom: -30px; right: -37px; border: 20px solid #eee; border-radius: 25px; box-sizing: content-box; } #facebook-icon:after { content: "/20"; position: absolute; width: 55px; top: 50px; height: 20px; background: #eee; right: 5px; box-sizing: content-box; } Moon via Omid Rasouli #moon { width: 80px; height: 80px; border-radius: 50%; box-shadow: 15px 15px 0 0 red; } Flag via Zoe Rooney #flag { width: 110px; height: 56px; box-sizing: content-box; padding-top: 15px; position: relative; background: red; color: white; font-size: 11px; letter-spacing: 0.2em; text-align: center; text-transform: uppercase; } #flag:after { content: ""; position: absolute; left: 0; bottom: 0; width: 0; height: 0; border-bottom: 13px solid #eee; border-left: 55px solid transparent; border-right: 55px solid transparent; } Cone via Omid Rasouli #cone { width: 0; height: 0; border-left: 70px solid transparent; border-right: 70px solid transparent; border-top: 100px solid red; border-radius: 50%; } Cross via Kaya Basharan #cross { background: red; height: 100px; position: relative; width: 20px; } #cross:after { background: red; content: ""; height: 20px; left: -40px; position: absolute; top: 40px; width: 100px; } Base via Josh Rodgers #base { background: red; display: inline-block; height: 55px; margin-left: 20px; margin-top: 55px; position: relative; width: 100px; } #base:before { border-bottom: 35px solid red; border-left: 50px solid transparent; border-right: 50px solid transparent; content: ""; height: 0; left: 0; position: absolute; top: -35px; width: 0; } Pointer via Amsakanna Freethinker #pointer { width: 200px; height: 40px; position: relative; background: red; } #pointer:after { content: ""; position: absolute; left: 0; bottom: 0; width: 0; height: 0; border-left: 20px solid white; border-top: 20px solid transparent; border-bottom: 20px solid transparent; } #pointer:before { content: ""; position: absolute; right: -20px; bottom: 0; width: 0; height: 0; border-left: 20px solid red; border-top: 20px solid transparent; border-bottom: 20px solid transparent; } Lock via Colin Bate #lock { font-size: 8px; position: relative; width: 18em; height: 13em; border-radius: 2em; top: 10em; box-sizing: border-box; border: 3.5em solid red; border-right-width: 7.5em; border-left-width: 7.5em; margin: 0 0 6rem 0; } #lock:before { content: ""; box-sizing: border-box; position: absolute; border: 2.5em solid red; width: 14em; height: 12em; left: 50%; margin-left: -7em; top: -12em; border-top-left-radius: 7em; border-top-right-radius: 7em; } #lock:after { content: ""; box-sizing: border-box; position: absolute; border: 1em solid ted; width: 5em; height: 8em; border-radius: 2.5em; left: 50%; top: -1em; margin-left: -2.5em; }

The post The Shapes of CSS appeared first on CSS-Tricks.

Developing With Automad

Css Tricks - Fri, 09/28/2018 - 5:20am

Selecting the right CMS for a blog or website can be difficult. Every web project has its own needs and requirements, meaning one CMS may be a better fit for one site but not so much for a different site. Simple solutions might be lacking some essential features, while more complex systems can create easily overhead for a given task.

I want to cover Automad, a CMS that is less-known than, say, a behemoth like WordPress, but still offers some powerful features like it while maintaining the nimbleness of smaller, simpler solutions, like static site generators.

Specifically, Automad fills a gap between larger and smaller offerings in a few key ways:

  • It is file-based, but does not require a database. This ensures quick setup, portability, security, speed, and easy deployment.
  • Even without a database, it offers database features like searching, tagging, filtering, and sorting.
  • A multi-layer caching engine caches content stored in the file system efficiently.
  • The browser-based dashboard and the in-page (“live") edit mode allows for intuitive content management.

But what makes Automad really different, is its integrated template engine. Templating is a core requirement for may CMSs because it creates and sets the base for a site’s visual display. Since Automad’s template engine is so close to the core, it allows you to create templates with complex navigations and to batch process images using a clean and short syntax. You’ll feel the difference once you get your hands on it, and we’ll walk through an example together in just a bit.

But first, a quick overview of templating

As a designer or a developer, you’re probably curious about how to develop themes and templates for Automad. I mean, it’s the crux for why any of us really use a CMS in the first place. If you’ve done any level of theming with WordPress, then working with Automad will feel vaguely familiar, and perhaps even easier.

The minimal requirement for creating an Automad theme is a single .php file and a theme.json file bundled together in a subdirectory you create inside the top-level /packages directory in a default Automad installation:

packages/ yourTheme/ yourTemplate.php theme.json

The tutorial package shipped with Automad provides a good starting point for understanding the basic concepts of themes.

A look at the syntax used in Automad templates

While it is possible to write templates in plain PHP, it is not required and actually not recommended. The reason is that Automad’s own template syntax is shorter, more readable, and integrates well with the user interface by automatically listing all of the used variables in the dashboard. It can be seamlessly mixed into HTML markup.

Basically, the syntax can be split into two groups:

  1. Echoing content: @{ variable }
  2. Statements, like functions, loops and conditionals: <@ function @> or <@ statement @>…<@ end @>
Echo content

Let’s say we want to pull the body content for a post into a template and we have a variable set up for that called text. In WordPress, this would be a global variable (the_content) that is called in PHP:

<?php the_content(); ?>

In Automad, we can do the same without PHP:

<p>@{ text }</p>

It is possible to manipulate the output of variables by passing the value to a function using the pipe (|) operator. The following example shows how to shorten a given text to a maximum of 100 characters without cutting words:

@{ text | shorten (100) }

This would be the same of thing you might do to define the excerpt of a post in WordPress using a function:

/* Limit excerpt to 20 words */ function my_custom_excerpt_length( $length ) { return 20; } add_filter( 'excerpt_length', 'wpdocs_custom_excerpt_length', 999 ) }

One of the key benefits of some CMS solutions, like Jeykll, is that using Markdown to create site content is a native feature. Automad can do the same. Let’s say we want to convert Markdown text to HTML. It’s pretty darn simple (and efficient) using the pipe operator:

@{ text | markdown } Using statements

Statements are a handy way to define content and display it conditionally. Unlike variables, statements are wrapped in <@ … @> delimiters. The following example can be used to create a simple top level menu by using the nav function:

<@ nav { context: "/", class: "nav" } @>

Let’s say you want to display your post content by default but display a fallback if that content does not exist for some reason. That’s where we can put conditional statements and control structures to use:

<# If the post content exists then display... #> <@ if @{ text } @> <p>...</p> <# Otherwise, display this... #> <@ else @> <p>Sorry, no content here!</p> <# OK, no more conditions. #> <@ end @>

Want to create a loop? This is where display a list of posts or any repeatable content that matches a condition is super useful. We can do that in Automad by providing one or more glob patterns in a foreach loop.

For example, let’s display all JPG and PNG images for a post cropped at 400x300 with their captions:

<@ foreach in "*.jpg, *.png" { width: 400, height: 300, crop: true } @> <img src="@{:fileResized}" width="@{:widthResized}" height="@{:heightResized}"> <p>@{:caption}</p> <@ end @>

Did you catch that?! As shown by this example, a remarkable Automad feature is the ability to embed resizing options for each matching file inside the loop statement. No more complicated functions to register sizes that then need to be called in the template!

It’s worth noting that foreach loops can also be used to iterate over objects. Automad knows multiple types of objects. One of the most important objects is pagelist because of its ability to output all of the pages on the site, like you might want to do when building navigation. When iterating a pagelist, the context changes with every iteration to the current page in the loop. That way, it is possible to use page variables within the loop’s code block.

To configure the pagelist, we can use the newPagelist function like this:

<@ newPagelist { context: "/", type: "children" } @> <ul> <@ foreach in pagelist @> <li><a href="@{ url }">@{ title }</a></li> <@ end @> </ul> A sneak peek behind the scenes for you super geeks &#x1f913;

Automad’s template interpreter is written in pure PHP and it processes templates on the fly. Therefore, no extra build process is required at all. The list of system requirements is also rather short. A web server (Apache or Nginx) and PHP 5.4+ is already enough to run a site. Pages are only rendered when content has changed or after system updates.

Automad’s multi-layer caching engine stores the rendered pages in separate .html files as well as all crawled data in the file system as a kind of content object. That object is also used to speed up page searching and filtering.

Due to that mechanism, it is possible to either edit the content of a site directly in production online using the browser-based dashboard or edit a site locally and deploy it via Git or plain rsync.

Let’s write some code!

The best way to get acquainted with anything on the web is to just build websites. Here are some examples of how we’d get started with that using Automad.

Example 1: Recursive navigation

Creating a site-tree navigation is a good example for using recursion in templates. Conceptually, creating such a recursive navigation can be split into three steps:

  1. Defining a reusable snippet of code to create a single branch of the site-tree which calls itself conditionally
  2. Configuring a dynamic pagelist which automatically only contains children of its current context
  3. Defining the root page of the site-tree (for instance the homepage) and call the recursive snippet initially

Let’s break those steps down into greater detail...

Defining a reusable snippet of code

In Automad, blocks of code can be defined to be reused at a later point by using the snippet keyword. Regarding this example, the following snippet will call itself conditionally when looping through a pagelist and the active page of the current iteration itself has children pages:

<@ snippet navigation @> <ul class="menu-list"> <@ foreach in pagelist @> <li> <a href="@{ url }">@{ title }</a> <# Call snippet recursively. #> <@ navigation @> </li> <@ end @> </ul> <@ end @> Configuring a dynamic pagelist

The pagelist has to be configured a children type. The context (or parent page) will always change recursively within the snippet defined above in that way. The pagelist will automatically only contain children pages of the currently processed page.

<@ newPagelist { type: 'children' } @> Defining the root page

In the last step, the root context of the navigation tree has to be defined and the snippet has to be called once to initiate the recursion. The with statement is used here to change the context to the homepage.

<div class="menu"> <@ with '/' @> <@ navigation @> <@ end @> </div>

A complete working tutorial template is already included in Automad.

Example 2: Working with files

Since images are super important for content management, working with them should be as easy and intuitive as possible. Automad's template language provides handy methods for basic image processing, like resizing and cropping. When using a single image or iterating a set of images, resizing options can be passed to a with statement or foreach loop. Check out the tutorial that ships with Automad to get started quickly.

<@ foreach in '*.jpg, *.png' { width: 400, height: 300, crop: true } @> <# Code to be used for each image in the filelist. #> <img src="@{ :fileResized }" alt="@{ :basename }" title="@{ :file }" width="@{ :widthResized }" height="@{ :heightResized }" > <p>@{ :caption | markdown }</p> <@ else @> <# Code to be used when the list of images is empty. #> <@ end @>

Instead of using a glob pattern in the foreach loop, it is also possible to use the filelist object.

If you look at the example code above, you will notice the use of certain runtime variables to access image properties within a code block. While the :file variable represents the original file, :fileResized refers to path of the resized and cached version. The :caption variable enables you to get the caption text stored along with the file.

What will you build?

We merely scratched the surface of Automad here, but hopefully everything we covered gives you a good idea of the possibilities it provides for content management. While there is no one-size-fits-all mold in the CMS world, there will likely be scenarios where a CMS that sits somewhere between the robust and slimmed-down options will come in handy.

Additional Resources

The post Developing With Automad appeared first on CSS-Tricks.

Fronteers considers applying for W3C membership

QuirksBlog - Thu, 09/27/2018 - 5:19am

Months of planning come to a head, and the cat is out of the bag. Fronteers, the Dutch professional association of front-end developers, is planning to apply for W3C membership and appoint Rachel Andrew as our paid representative. This would solve the problem of front-end developer representation in W3C.

Note that this plan will be submitted to the Fronteers members on 19th of October, and that they can vote it down.

Below is the press release, in case you’re interested.

Also, I wrote an A List Apart article, Rachel wrote a Smashing Magazine article, and if you read Dutch you should read the Fronteers blog post that contains the complete proposal.

Press release

On its annual general member meeting on 19th of October, the Fronteers board will propose to become a member of the World Wide Web Consortium (W3C), and to hire Rachel Andrew as our representative in that standards body. By becoming a W3C member, Fronteers aims to be the first membership organisation to give front-end developers a voice (and vote) in web standards.

While W3C has always desired input from front-end developers, and some of them became Invited Experts and contributed to the discussions, these experts had to do so in their own spare time and at their own expense. Fronteers aims to change that.

Our W3C membership is not yet set in stone: the Fronteers general member meeting will have to approve of this plan (and its financial consequences), which will be laid before it on 19th of October. Rachel Andrew will be present to explain the consequences to the Fronteers members.

Founded in 2007, Fronteers is the professional association of Dutch front-end developers. It is best known for its annual Fronteers conference in October, but it has been locally active with workshops, meet-ups, a job board, and other activities for Dutch front-enders.

The World Wide Web Consortium (W3C) is the international organisation whose members and full-time staff, helped by specialised members of the public, develop the web standards used in all of today's browsers.

Rachel Andrew is a British front-end and back-end developer, speaker, author, and the editor-in-chief of Smashing Magazine. As an Invited Expert to W3C, especially for CSS layout matters such as flexbox and grid, she has ample experience in the standardisation process.

Nested Links

Css Tricks - Thu, 09/27/2018 - 4:15am

The other day I posted an image, quite literally as a thought exercise, about how you might accomplish "nested" links. That is, a big container that is linked to one URL that contains a smaller container or text link inside of it that goes to another URL. That's harder than it might seem at first glance. The main reason being that...

<!-- this is invalid and won't render as expected --> <a href="#one"> Outside <a href="#two"> Inside </a> </a>

Eric Meyer once called for more flexible linking, but even that doesn't quite handle a situation where one link is nested inside another.

Here's what happens with that HTML, by the way:

The nested link gets kicked out.

My first inclination would be to simply not nest the links in the markup, but make them appear nested visually. Some folks replied to the tweet, including Nathan Smith, who shared that same thought: have a relatively positioned parent element and absolutely position both links. The larger one could fill up the whole area and the smaller one could sit on top of it.

See the Pen "Nested" links by Nathan Smith (@nathansmith) on CodePen.

It's finicky, as you'll need magic numbers to some degree to handle the spacing and variable content.

My second inclination would be to deal with it in JavaScript.

<div onclick="window.location=''" style="cursor: pointer;" tabindex="1" > Outside <a href=""> Inside </a> </div>

I have literally no idea how kosher that is from an accessibility perspective. It looks gross to me so I'm just going to assume it's bad news.

Speaking of accessibility, Heydon Pickering has a whole article about card components which is a popular design pattern where this situation often comes up. His solution is to have a relatively positioned parent element, then a normally-placed and functional main link. That first link has an absolutely positioned pseudo-element on it covering the entire card. Any sub-links are relatively positioned and come after the initial link, so they'd sit on top of the first link by way of z-index.

Demo with author link.

And speaking of stacking pseudos, that's the approach Sean Curtis uses here:

See the Pen Pretend nested links by Sean Curtis (@seancurtis) on CodePen.

Other solutions in the "crafty" territory might be:

Sara Soueidan responded with her own post!

I had the same requirement a couple of years ago when I was building the front-end foundation for Smashing Magazine. So I thought I’d write my response to Chris’s thread out in the form of a blog post.

Sara has written about this with much more detail and care than I have here, so definitely check that out. It looks like both she and Heydon have landed on nearly the same solution, with the pseudo-element cover that contains sub-links poking above it as needed.

Have you ever done it another way? Plenty of UX and a11y to think abbout!

The post Nested Links appeared first on CSS-Tricks.

Test out the cloud platform developers love for free with a $100 credit

Css Tricks - Thu, 09/27/2018 - 4:12am

(This is a sponsored post.)

DigitalOcean invites you to experience a better, faster and simpler cloud platform designed to scale based on your needs. Get started for free with a $100 credit toward your first project and discover why the most innovative companies are already hosting on DigitalOcean.

Direct Link to ArticlePermalink

The post Test out the cloud platform developers love for free with a $100 credit appeared first on CSS-Tricks.

A Minimal JavaScript Setup

Css Tricks - Wed, 09/26/2018 - 3:44am

Some people prefer to write JavaScript with React. For others, it’s Vue or jQuery. For others still, it is their own set of tools or a completely blank document. Some setups are minimal, some allow you to get things done quickly, and some are crazy powerful, allowing you to build complex and maintainable applications. Every setup has advantages and disadvantages, but positives usually outweigh negatives when it comes to popular frameworks verified and vetted by an active community.

React and Vue are powerful JavaScript frameworks. Of course they are — that’s why both are trending so high in overall usage. But what is it that makes those, and other frameworks, so powerful? Is it the speed? Portability to other platforms like native desktop and mobile? Support of the huge community?

The success of a development team starts with an agreement. An agreement of how things are done. Without an agreement, code would get messy, and the software unsustainable quite quickly, even for relatively small projects. Therefore, a lot (if not most) of the power of a framework lies within this agreement. The ability to define conventions and common patterns that everyone adheres to. That idea is applicable to any framework, JavaScript or not. Those "rules" are essential to development and bring teams maintainability at any size, reusability of code, and the ability to share work with a community in a form anyone will understand. That’s why we can web search for some component/plugin that solves our problem rather than writing something on our own. We rely on open-source alternatives, no matter what framework we use.

Unfortunately, there are downsides to frameworks. As Adrian Holovaty (one of the Django creators) explains in his talk, frameworks tend to get bulky and bloated with features for one particular use case. It could be the inclusion of a really good idea. It could also be a desire to provide a one-size-fits-all solution for anyone and everyone’s needs. It could be to remain popular. Either way, there are downsides to frameworks in light of all the upsides they also have.

In server-rendered world, where we work with content that's delivered to the browser from a server, this "framework mission" is filled with skills, ideas, and solutions that people share with co-workers, friends, and others. They tend to adopt consistent development rules and enforce them within their teams or companies, rather than relying on a predefined framework. For a long time, it’s been jQuery that has allowed people to share and reuse code on a global scale with its plugins — but that era is fading as new frameworks are entering the fold.

Let’s take a look at some core points that any framework — custom or not — ought to consider essential for encouraging a maintainable and reusable codebase.

Naming conventions

Some might say that naming is the hardest part of development. Whether it’s naming JavaScript variables, HTML classes, or any other number of things, a naming convention has a big impact on how we work together because it adds context and meaning to our code. A good example of a naming convention is BEM, a CSS methodology created by the folks at Yandex and adopted by many, many front-enders. That sort of standardization and consistency can help inform our objective, which is to have a standard convention for naming JavaScript selectors.

This situation might seem familiar: you revisit a project after a few months and you see some behavior happening on the page — maybe something you want to modify or fix. However, finding the source of that behavior can be a tricky thing. Is it the id attribute I should search for? Is it one of the classes? Maybe the data attribute for this particular element?

I think you get the point. What helps is having some kind of convention to simplify the process and make everyone work with the same names. And it doesn’t really matter if we’re going with classes (e.g. js-[name]) or data attributes (e.g. data-name="[name]"). All that matters is that the names conform to the same style. Surely enough, any framework you will meet will enforce a naming convention of some sort as well, whether it’s React, Vue, Bootstrap, Foundation, etc.


A developer will likely struggle with JavaScript scope at some point in time, but we are specifically focusing on DOM scope here. No matter what you do with JavaScript, you’re using it to affect some DOM element. Limiting parts of the code to a DOM element encourages maintainability and makes code more modular. Components in both React and Vue operate in a similar fashion, although their "component" concept is different than the standard DOM. Still, the idea scopes the code to a DOM element that is rendered by those components.

While we’re on the topic of DOM manipulation, referencing elements within the root element of the component is super helpful because it help avoids the constant need to select elements. React and Vue do this out of the box in a very good way.


In the past, the page lifecycle was very straightforward: the browser loaded the page and the browser left the page. Creating or removing event listeners, or making code run at the right time was much simpler, as you would simply create everything you need on load, and rarely bother with disabling your code, since the browser would do it for you by default.

Nowadays, the lifecycle tends to be much more dynamic, thanks to state management and the way we prefer to manipulate changes directly to the DOM or load the contents of pages with JavaScript. Unfortunately, that usually brings some issues where you may need to re-run parts of your code at certain times.

I can't tell how many times in my life I’ve had to play around with code to get my event handlers to run correctly after re-writing part of the DOM. Sometimes it is possible to solve this with event delegation. Other times, your code handlers don't run at all or run several times because they are suddenly attached twice.

Another use case would be the need to create an instance of libraries after changing the DOM, like "fake selects."

In any case, the lifecycle is important and limiting your code to a DOM element certainly helps here as well, since you know that the code applied to that element needs to be re-run in case the element is re-rendered.

Frameworks do the same with functions as componentDidMount or componentDidUpdate, which give you an easy way of running code exactly when you need it.


Copying code from somewhere else and reusing it is super common. Who hasn’t used a snippet from a past project or an answer from StackOverflow, right? People even invented services like npm meant for one thing: to easily share and reuse code. There is no need to reinvent the wheel and sharing code with others is something that is convenient, handy, and often more efficient than spinning something up from scratch.

Components, whether it's React, Vue, or any other building block of a framework encourage reusability by having a wrapper around a piece of code that serves some specific purpose. A standardized wrapper with an enforced format. I would say this is more of a side effect of having some base we can build on, than an intentional effort for reusability, as any base will always need some standard format of a code it can run, the same way programming languages have a syntax we need to follow… but it is a super convenient and useful side effect, for sure. By combining this gained reusability with package managers like Yarn, and bundlers like webpack, we can suddenly make code written by many developers around the world work together in our app with almost no effort.

While not all code is open-source and shareable, a common structure will help folks in smaller teams as well, so anyone is able to understand most of the code written within the team without having to consult its author.

DOM manipulation with performance in mind

Reading and writing to the DOM is costly. Developers of front-end frameworks keep that in mind and try to optimize as much as possible with states, virtual DOM and other methods to make changes to the DOM when it's needed and where it's needed… and so should we. While we’re more concerned with server-rendered HTML, most of the code ends up reading or writing to the DOM. After all, that’s what JavaScript is for.

While most of the changes of the DOM are minimal, they can also occur quite often. A nice example of frequent reading/writing is executing a script on page scroll. Ideally, we would like to avoid adding classes, attributes or changing the contents of elements directly in the handler, even if we write the same classes, attributes or contents because our changes still get processed by the browser and are still expensive, even when nothing changes for the user.


Last, but not least: size. Size is critical or at least should be for a framework. The code discussed in this article is meant to be used as a base across many projects. It should be as small as possible and avoid any unnecessary code that could be added manually for one-off use cases. Ideally, it should be modular so that we can pull pieces of it out à la carte, based on the specific needs for the project at hand.

While the size of self-written code is usually reasonable, many projects end up having at least some dependencies/libraries to fill in gaps, and those can make things quite bulky really fast. Let's say we have a carousel on a top-level page of a site and some charts somewhere deeper. We can turn to existing libraries that would handle these things for us, like slick carousel (10 KB minified/gzipped, excluding jQuery) and highcharts (73 KB minified/gzipped). That’s over 80 KB of code and I’d bet that not every byte is needed for our project. As Addy Osmani explains, JavaScript is expensive and its size is not the same as other assets on a page. It's worth keeping that in mind the next time you find yourself reaching for a library, though it shouldn't discourage you from doing it if the positives outweigh the negatives.

A look at a minimal solution we call Gia

Let's take a look at something I’ve been working on and using for a while with my team at Giant. We like JavaScript and we want to work directly with JavaScript rather than a framework. But at the same time, we need the maintainability and reusability that frameworks offer. We tried to take some concepts from popular frameworks and apply them to a server-rendered website where the options for a JavaScript setup are so wide, and yet so limited.

We'll go through some basic features of our setup and focus on how it solves the points we’ve covered so far. Note that many of the solutions to our needs are directly inspired by big frameworks, so if you see some similarities, know that it’s not an accident. We call it Gia (get it, like short for Giant?!) and you can get it from npm and find the source code on GitHub.

Gia, like many frameworks, is built around components that give you a basic building block and some advantages we’ll touch on in a bit. But don't confuse Gia components with the component concepts used by React and Vue, where all your HTML is a product of the component. This is different.

In Gia, a component is a wrapper for your own code that runs in the scope of a DOM element, and the instance of a component is stored within the element itself. As a result, an instance is automatically removed from the memory by the garbage collector in case the element is removed from the DOM. The source code of the component can be found here and is fairly simple.

Apart from a component, Gia includes several helpers to apply, destroy and work with the component instance or communicate between components (with standard eventbus included for convenience).

Let’s start with a basic setup. Gia is using an attribute to select elements, along with the name of the component to be executed (i.e. g-component="[component name]"). This enforces a consistent naming convention. Running the loadComponents function creates the instances defined with the g-component attribute.

See the Pen Basic component by Georgy Marchuk (@gmrchk) on CodePen.

Gia components also allow us to easily select elements within the root element with the g-ref attribute. All that needs to be done is to define the refs that are expected and whether we’re working with a single element or an array of them. Reference is then accessible in the this.ref object within the component.

See the Pen Component with ref elements by Georgy Marchuk (@gmrchk) on CodePen.

As a bonus, default options can be defined in the component, which are automatically rewritten by any options included in g-options attribute.

See the Pen Component with options by Georgy Marchuk (@gmrchk) on CodePen.

The component includes methods that are executed at different times, in order to solve the lifecycle issue. Here’s an example that shows how a component can be initialized or removed:

See the Pen load/remove components by Georgy Marchuk (@gmrchk) on CodePen.

Notice how loadComponents function doesn't apply the same component when it already exists.

It is not necessary to remove listeners attached to the root element of a component or elements within it before re-rendering them since the elements would be removed from the DOM anyway. However, there can be some listeners created on global objects (e.g. window), like the ones used for scroll handling. In this case, it is necessary to remove the listener manually before destroying the component instance in order to avoid memory leaks.

The concept of a component scoped to a DOM element is similar in its nature to React and Vue components, but with a key exception that the DOM structure is outside of the component. As a result, we have to make sure it fits the component. Defining the ref elements certainly helps, as Gia component will tell you when the required refs are not present. That makes the component reusable. The following is example implementation of a basic carousel that could be easily reused or shared:

See the Pen Basic carousel component by Georgy Marchuk (@gmrchk) on CodePen.

While we’re talking about reusability, it’s important to mention that components don't have to be reused in their existing state. In other words, we can extend them to create new components as any other JavaScript class. That means we can prepare a general component and build upon it.

To give an example, a component that would give us the distance between the cursor and the center of an element seems like a thing that could be useful someday. Such a component can be found here. After having that ready, it’s ridiculously easy to build upon it and work with provided numbers, as the next example shows in the render function, although we could argue about the usefulness of this particular example.

See the Pen ZMXMJo by Georgy Marchuk (@gmrchk) on CodePen.

Let's try to look into optimized DOM manipulations. Detecting if a change to the DOM is supposed to happen can be manually stored or checked without directly accessing the DOM, but that tends to be a lot of work which we might want to avoid.

This is where Gia really drew inspiration from React, with simple, stripped down component state management. The state of a component is set similarly to states in React, using a setState function.

That said, there is no rendering involved in our component. The content is rendered by the server, so we need to make a use of the changes in state elsewhere. The state changes are evaluated and any actual changes are sent to the stateChange method of a component. Ideally, any interaction between the component and the DOM would be handled in this function. In case some part of the state doesn’t change, it won’t be present in the stateChanges object passed into a function and therefore won't be processed — the DOM won't be touched without it being truly necessary.

Check the following example with a component showing sections that are visible in the viewport:

See the Pen Sections in viewport component by Georgy Marchuk (@gmrchk) on CodePen.

Notice how writing to the DOM (visualized by the blink) is only done for items where the state actually changes.

Now we are getting to my favorite part! Gia is truly minimal. The entire bundle containing all the code, including all the helpers, takes up a measly 2.68 KB (minified/gzipped). Not to mention that you most likely won't need all of Gia’s parts and would end up importing even less with a bundler.

As mentioned earlier, the size of the code can rapidly increase by including third-party dependencies. That’s why Gia also includes code splitting support where you can define a dependency for a component, which will only be loaded when the component is being initialized for the first time, without any additional setup required to the bundler. That way, the bulky libraries used somewhere deep within your site or application don’t have to slow things down.

In case you decide one day that you really want to take advantage of all the goodies big frameworks can offer somewhere in your code, there is nothing easier than just loading it like any other dependency for the component.

class SampleComponent extends Component { async require() { this.vue = await import('vue'); } mount() { new this.vue({ el: this.element, }); } } Conclusion

I guess the main point of this article is that you don't need a framework to write maintainable and reusable code. Following and enforcing a few concepts (that frameworks use as well) can take you far on its own. While Gia is minimal and does not have many of the robust features offered by big players, like React and Vue, it still helps us get that clean structure that is so important in the long term. It includes some more interesting stuff that didn't make the cut here. If you like it so far, go check it out!

GitHub Repo

There are lots and lots of use cases, and different needs require different approaches. Various frameworks can do plenty of the work for you; in other cases, they may be constraining.

What is your minimal setup and how do you account for the points we covered here? Do you prefer a framework or non-framework environment? Do you use frameworks in combination with static site generators like Gatsby? Let me know!

The post A Minimal JavaScript Setup appeared first on CSS-Tricks.

The “Developer Experience” Bait-and-Switch

Css Tricks - Wed, 09/26/2018 - 3:43am

Alex Russell describes his thoughts on the current state of JavaScript and how we might sometimes put a ton of focus on the ease-of-use of development at the expense of user experience. So, for example, we might pick a massive framework to make development easier and faster but then that might have an enormous impact on the user.

Alex describes it as substituting “developer value for user value.”

The “developer experience” bait-and-switch works by appealing to the listener’s parochial interests as developers or managers, claiming supremacy in one category in order to remove others from the conversation. The swap is executed by implying that by making things better for developers, users will eventually benefit equivalently. The unstated agreement is that developers share all of the same goals with the same intensity as end users and even managers. This is not true.

Here’s the kicker, though:

JavaScript is the web’s CO2. We need some of it, but too much puts the entire ecosystem at risk. Those who emit the most are furthest from suffering the consequences — until the ecosystem collapses. The web will not succeed in the markets and form-factors where computing is headed unless we get JS emissions under control.

By that standard, it could also stand to reason that the work we put into “design systems” falls into this trap. But there is something to be said about achieving ease of use on this front: a more consistent codebase is probably a very good thing for accessibility, UX consistency, etc. etc.

So, although I agree with Alex’s premise here, I’m not entirely sure I agree wholeheartedly on this subject.

Direct Link to ArticlePermalink

The post The “Developer Experience” Bait-and-Switch appeared first on CSS-Tricks.

Don’t use empty or low content for your design system grid examples

Css Tricks - Tue, 09/25/2018 - 8:44am

Dave and I had Jen Simmons on ShopTalk the other day. Jen was talking about Intrinsic Web Design and how one of the core tenets of it is grids with rows and columns that don't necessarily change at the same rate or ones that have essentially different rules for how they behave.

For example, take this (contrived) grid setup:

.grid { display: grid; grid-template-columns: 1fr minmax(50px, 100px) 20% auto; }

Each of those columns will behave differently.

I'm just wrapping my head about this, and definitely don't fully understand it. Here's what it seems like to me, numbered 1-4 based on the "strength" (I guess?) of the width.

.grid { display: grid; grid-template-columns: 1fr /* #4 - Weakest, will fill remaining space */ minmax(50px, 100px) /* #3 - Will only start changing when other columns force it */ 20% /* #1 - Definite size, steady */ auto /* #2 - Indefinite size, entirely based on content, pushy */ ; }

This is much different from quite a long history of how we've set up grid columns in the past. Float-based grids typically use percentages (a definite size) to set columns. Same with inline-block-based grids, typically.

Even with grid, if you set up all your columns with all percentages or all fractional units, you'd likely have a steady grid in which the content inside won't mess with sizing. But Jen is saying that it's interesting to have a grids where the content has a say in how they size. Embrace it. Sounds fun to me.

But anyway, say you're setting up a grid that uses mixed values for column widths like this. Don't do that with totally empty columns, otherwise, you'll get a false sense of how those columns will behave.

Just look at this demo where these four grids have the exact same setup and all that is different is the amount of text in each column.

See the Pen Different Collapse Rates of Different Column Width Values by Chris Coyier (@chriscoyier) on CodePen.


The post Don’t use empty or low content for your design system grid examples appeared first on CSS-Tricks.

Putting things on top of other things

Css Tricks - Tue, 09/25/2018 - 7:09am

A plain-language romp through the trials and tribulations of z-indexby Isabel Brison. On the surface, z-index seems simple. It's a number and it represents what is on top of what... assuming it is positioned... and assuming it is within the same stacking context as the other things.

... that is the gist of it: stacking contexts are caused by a variety of properties and the main reasons for their existence are performance concerns and ease of implementation by browsers. They are not always related to z-index or ordering; they pop up wherever it makes sense to have several elements all on the same layer for rendering purposes.

Direct Link to ArticlePermalink

The post Putting things on top of other things appeared first on CSS-Tricks.

The Complete Guide to Lazy Loading Images

Css Tricks - Tue, 09/25/2018 - 4:32am

Images are critical. Whether it is marketing banners, product images or logos, it is impossible to imagine a website without images. Sadly though, images are often heavy files making them the single biggest contributor to the page bloat. According the HTTP Archive’s State of Images report, the median page size on desktops is 1511 KB and images account for nearly 45% (650 KB) of that total.

That said, it’s not like we can simply do away with images. They’re too important to the overall user experience. Instead, we need to make our web pages load really fast with them. In this guide, we will cover all of the ins and outs of lazy loading images, a technique that helps improve the time it takes for a web page to load by deferring image loads until they are needed.

Before we dive right in, here is a sample video that demonstrates the concept. In short, a gray placeholder box is rendered on the page until it scrolls into view—at which point the actual image loads in place of the box.

Chapter 1: What is Lazy Loading?

We often associate the word “lazy" with avoiding work as long as possible, or the sheer act of wanting to do nothing at all.

Similarly, lazy loading defers the loading of resources on the page as long as they are not needed. Instead of loading them right away, which is what normally happens, we allow them to load later.

Lazy Loading is a set of techniques in web and application development that defers the loading of resources on a page to a later point in time—when those resources are actually needed instead of loading them up front. These techniques help in improving performance, better utilization of the device’s resources and reducing associated costs.

The technique of lazy loading can be applied to just about any resources on a page. For example, even a JavaScript file can be held back if it is best not to load it initially. Same deal for an image—load it when we need it.

We will stick to lazy loading images in this guide, but it’s good to know it can be applied to other assets.

Chapter 2: Why Lazy Load at All?

If the user never scrolls to the point of the page that contains the image, then the user will never see that image. It also never loads in the first place because, hey, it was never needed.

You may already start to see how this benefits both you and the user. Here are two of the advantages we get with lazy loading.

Performance Gains

The obvious benefit is that we get smaller web pages that load faster. Lazy loading reduces the number of images that need to be loaded on a page up front. Fewer image requests mean fewer bytes to download. And fewer bytes to download means the page renders faster than if those bytes and requests were being made.

This ensures that any device on any network is able to download and process the remaining resources much faster. Hence, the time from request to render becomes smaller and the page becomes usable much earlier. Win-win!

Cost reduction

The second benefit is for you as a website administrator. Cloud hosting services, like Content Delivery Networks (CDNs) or web servers or storages, deliver images (or any asset for that matter) at a cost based on the number of bytes transferred. A lazy loaded image may never get loaded if the user never reaches it. Thus, you may reduce the total bytes delivered on the page and ultimately save yourself a few pennies in the process. This is especially true for users that instantly bounce off a page or interact only with the top portion of the content.

The reduction in bytes transferred from your delivery network or server reduces delivery costs. This will become more apparent as we explore lazy loading in the coming sections.

Just how much will you save? You can find out which images are a candidate for lazy loading and how many bytes you can save on the initial page load by using the Google Lighthouse audit tool. This has a section dedicated for offscreen images. You can also use ImageKit’s website analyzer to identify if your website uses lazy loading or not apart from other critical image related optimizations on your page.

Lazy loading is critical not only to good performance but also to deliver a good user experience. Since combining performance and user experience with lazy loading is important and challenging, we will continue to address this topic in more detail throughout this guide after we have looked at different ways to lazy load images.

Chapter 3: Lazy Loading Techniques for Images

There are two common ways that we load images to a page: the <img> tag and the CSS background-image property. We will first look at the more common of the two, the <img> tag and then move to CSS background images.

Lazy loading images in an image tag

Let’s start with the typical HTML markup for an image:

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

The markup for lazy loading images is pretty similar.

Step one is to prevent the image load up front. The browser uses the src attribute of the tag to trigger the image load. It doesn’t matter if it is the first or the 1,000th image in your HTML. If the browser gets the src attribute, it will trigger the image to be downloaded, regardless of whether it is in or out of current view.

To defer the load, put the image URL in an attribute other than src. Let’s say we specify the image URL in the data-src attribute of the image tag. Now that src is empty and the browser won’t trigger the image load:

<img data-src="" />

Now that we’re preventing the image from loading, we need to tell the browser when to load it. Otherwise, it will never happen. For this, we check that as soon as the image (i.e. its placeholder) enters the viewport, we trigger the load.

There are two ways to check when an image enters the viewport. Let’s look at both of them with working code samples.

Method 1: Trigger the image load using Javascript events

This technique uses event listeners on the scroll, resize and orientationChange events in the browser. The scroll event is pretty clear cut because it watches where the user is on a page as scrolling occurs. The resize and orientationChange events are equally important. The resize event occurs when the browser window size changes, whereas orientationChange gets triggered when the device is rotated from landscape to portrait, or vice versa.

We can use these three events to recognize a change in the screen and determine the number of images that become visible on the screen and trigger them to load accordingly.

When any of these events occur, we find all the images on the page that are deferred and, from these images, we check which ones are currently in the viewport. This is done using an image’s top offset, the current document top position, and window height. If an image has entered the viewport, we pick the URL from the data-src attribute and move it to the src attribute and the image will load as a result.

Note that we will ask JavaScript to select images that contain a lazy class. Once the image has loaded, we’ll remove the class because it no longer needs to trigger an event. And, once all the images are loaded, we remove the event listeners as well.

When we scroll, the scroll event triggers multiple times rapidly. Thus, for performance, we are adding a small timeout to our script that throttles the lazy loading function execution so it doesn’t block other tasks running in the same thread in the browser.

Here is a working example of this approach.

See the Pen Lazy loading images using event handlers - example code by (@imagekit_io) on CodePen.

Note that the first three images in this example are loaded up front. The URL is present directly in the src attribute instead of the data-src attribute. This is essential for a good user experience. Since these images are at the top of the page, they should be made visible as soon as possible. There’s no need to wait for JavaScript to load them.

Method 2: Trigger the image load using the Intersection Observer API

The Intersection Observer API is relatively new. It makes it simple to detect when an element enters the viewport and take an action when it does. In the previous method, we had to bind events, keep performance in mind and implement a way to calculate if the element was in the viewport or not. The Intersection Observer API removes all that overhead by avoiding the math and delivering great performance out of the box.

Below is an example using the API to lazy load images. We attach the observer on all the images to be lazy loaded. Once the API detects that the element has entered the viewport, using the isIntersecting property, we pick the URL from the data-src attribute and move it to the src attribute for the browser to trigger the image load. Once this is done, we remove the lazy class from the image and also remove the observer from that image.

See the Pen Lazy loading images using IntersectionObserver - example code by (@imagekit_io) on CodePen.

If you compare the image loading times for the two methods (event listeners vs. Intersection Observer), you will find that images load much faster using the Intersection Observer API and that the action is triggered quicker as well— and yet the site doesn’t appear sluggish at all, even in the process of scrolling. In the method involving event listeners, we had to add a timeout to make it performant, which has a slightly negative impact on the user experience as the image load is triggered with a slight delay.

However, like any new feature, the support for Intersection Observer API is not available across all browsers.

This browser support data is from Caniuse, which has more detail. A number indicates that browser supports the feature at that version and up.

DesktopChromeOperaFirefoxIEEdgeSafari584555No16NoMobile / TabletiOS SafariOpera MobileOpera MiniAndroidAndroid ChromeAndroid FirefoxNo46No676962

So, we need to fall back to the event listener method in browsers where the Intersection Observer API is not supported. We have taken this into account in the example above.

Chapter 4: Lazy Loading CSS Background Images

A common background image in CSS:

.my-class { background-image: url('/path/to/some/image.jpg'); /* more styles */ }

CSS background images are not as straightforward as the image tag. To load them, the browser needs to build the DOM tree as well as the CSSOM tree to decide if the CSS style applies to a DOM node in the current document. If the CSS rule specifying the background image does not apply to an element in the document, then the browser does not load the background image. If the CSS rule is applicable to an element in the current document, then the browser loads the image.

Huh? This may seem complex at first, but this same behavior forms the basis of the technique for lazy loading background images. Simply put, we trick the browser into not applying the background-image CSS property to an element, till that element comes into the viewport.

Here is a working example that lazy loads a CSS background image.

See the Pen Lazy Loading background images in CSS by (@imagekit_io) on CodePen.

One thing to note here is that the JavaScript code for lazy loading is still the same. We are still using the Intersection Observer API method with a fallback to the event listeners. The “trick" lies in the CSS.

We have an element with ID bg-image that has a background-image. However, when we add the lazy class to the element, we can override the background-image property by setting the value of it to none in the CSS.

Since an element with an ID and a class has higher specificity in CSS than an ID alone, the browser applies the property background-image: none to the element initially. When we scroll down, the Intersection Observer API (or event listeners, depending on which method you choose) detects that the image is in the viewport, it removes the lazy class from the element. This changes the applicable CSS and applies the actual background-image property to the element, triggering the load of the background image.

Chapter 5: Creating a Better User Experience With Lazy Loading

Lazy loading presents a great performance benefit. For an e-commerce company that loads hundreds of product images on a page, lazy loading can provide a significant improvement in initial page loads while decreasing bandwidth consumption.

However, a lot of companies do not opt for lazy loading because they believe it goes against delivering a great user experience?(i.e. the initial placeholder is ugly, the load times are slow etc.).

In this section, we will try to solve some concerns around user experience with lazy loading of images.

Tip 1. Use the Right Placeholder

A placeholder is what appears in the container until the actual image is loaded. Normally, we see developers using a solid color placeholder for images or a single image as a placeholder for all images.

The examples we’ve looked at so far have used a similar approach: a box with a solid light gray background. However, we can do better to provide a more pleasing user experience. Below are some two examples of using better placeholders for our images.

Dominant Color Placeholder

Instead of using a fixed color for the image placeholder, we find the dominant color from the original image and use that as a placeholder. This technique has been used for quite some time by Google in its image search results as well as by Pinterest in its grid design.

Pinterest uses the dominant color of the image as the background color for image placeholders. (Source)

This might look complex to achieve, but Manuel Wieser has an elegant solution to accomplishing this by scaling down the image to down to a 1×1 pixel and then scale it up to the size of the placeholder—a very rough approximation but a simple, no-fuss way to get a single dominant color. Using ImageKit, the dominant color placeholder can be obtained using a chained transform in ImageKit as shown below.

<!-- Original image at 400x300 --> <img src=",h-300" alt="original image" /> <!-- Dominant color image with same dimensions --> <img src=",h-1:w-400,h-300" alt="dominant color placeholder" />

The placeholder image is just 661 bytes in size compared to the original image that is 12700 bytes—19x smaller. And it provides a nicer transition experience from placeholder to the actual image.

Here is a video demonstrating how this effect works for the user.

See the Pen Dominant color placeholder - Lazy loading images using IntersectionObserver - example code by (@imagekit_io) on CodePen.

Low Quality Image Placeholder (LQIP)

We can extend the above idea of using a dominant color placeholder further. Instead of using a single color, we use a very low-quality, blurred version of the original image as the placeholder. Not only does it look good, but it also gives the user some idea about what the actual image looks like and the perception that the image load is in progress. This is great for improving the perceived loading experience. This technique has been utilized by the likes of Facebook and Medium.

LQIP image URL example using ImageKit:

<!-- Original image at 400x300 --> <img src=",h-300" alt="original image" /> <!-- Low quality image placeholder with same dimensions --> <img src=",h-300,bl-30,q-50" alt="dominant color placeholder" />

The LQIP is 1300 bytes in size, still almost 10x smaller than the original image and a significant improvement in terms of visual experience over any other placeholder technique.

Here is a video demonstrating how this effect works for the user.

See the Pen LQIP placeholder - Lazy loading images using IntersectionObserver - example code by (@imagekit_io) on CodePen.

It is clear that using either dominant color or LQIP placeholders provides a smoother transition from the placeholder to the actual image, gives the user an idea of what is to come in place of that placeholder, and improves loading perception.

Tip 2: Add Buffer Time for Images to Load

When we discussed different methods to trigger image loads, we checked for the point of time where the image enters the viewport, i.e. the image load is triggered when the top edge of the image placeholder coincides with the bottom edge of the viewport.

The problem with this is that users might scroll really fast through the page and the image will need some time to load and appear on the screen. Combined with throttling possibly further delaying the load, the user may wind up waiting a few milliseconds longer for the image to show up. Not great for user experience!

While we can get a pretty good user experience using the Intersection Observer API for performance and LQIP for smoother transitions, there is another simple trick that you can use to ensure that the images are always loaded completely when they enter the viewport?: introduce a margin to the trigger point for images.

Instead of loading the image exactly when it enters the viewport, load it when it’s, let’s say, 500px before it enters the viewport. This provides additional time, between the load trigger and the actual entry in the viewport, for the images to load.

With the Intersection Observer API, you can use the root parameter along with the rootMargin parameter (works as standard CSS margin rule), to increase the effective bounding box that is considered to find the intersection. With the event listener method, instead of checking for the difference between the image edge and the viewport edge to be 0, we can use a positive number to add some threshold.

See the Pen Lazy loading images with additional threshold - example code by (@imagekit_io) on CodePen.

If you watch the following screencast closely, you’ll notice that the fifth image in the sequence is loaded when the third image is in view. Similarly, the sixth image is loaded when the fourth is in view, and so on. This way, we are giving sufficient time for the images to load completely and, in most cases, the user won’t see the placeholder at all.

If you didn’t notice earlier, in all our examples, the third image (image3.jpg) is always loaded up front, even though it is outside the viewport. This was also done following the same principal: ?load slightly in advance instead of loading exactly at the threshold for better user experience.

Tip 3: Avoid Content Reflow

This is another trivial point, which if solved, can help maintain a good user experience.

When there is no image, the browser doesn’t know the size it will take up. And if we do not specify it using CSS, then the enclosing container would have no dimensions, i.e. it will be read as 0x0 pixels.

When the image loads, the browser will drop it into the screen and reflow the content to fit it. This sudden change in the layout causes other elements to move around and it is called content reflow, or shifting. Michael Scharnagl goes into great depth explaining how this creates an unpleasant user experience.

This can be avoided by specifying a height and/or width for the enclosing container so that the browser can paint the image container with a known height and width. Later, when the image loads, since the container size is already specified and the image fits into that perfectly, the rest of the content around that container does not move.

Tip 4: Avoid Lazy Loading Every Image

This is a mistake that developers often make because it’s super tempting to think that deferring image loads is good all the time. But, like life itself, it is possible to have too much of a good thing. Lazy loading might reduce the initial page load, but it also might result in a bad user experience if some images are deferred when they should not be.

We can follow some general principles to identify which images should be lazy loaded. For example, any image that is present in the viewport, or at the beginning of the webpage, should probably not be lazy loaded. This applies to any header image, marketing banner, logos, or really anything that the user would see when initially landing on a page. Also, remember that mobile and desktop devices will have different screen sizes and hence a different number of images that will be visible on the screen initially. You’ll want to take the device that’s being used into account and decide which resources to load up front and which to lazy load.

Another example is any image that is even slightly off the viewport in the initial load should not probably not be lazy loaded. This is going by the principle discussed above—load slightly in advance. So, let’s say any image that is 500px or a single scroll from the bottom of the viewport can be loaded up front as well.

One more example is if the page is short. It may be just a single scroll or a couple of scrolls, or perhaps there are less than five images outside the viewport. In these cases, you can probably leave lazy loading out altogether. It would not provide any significant benefit to the end user in terms of performance and the additional JavaScript that you load on the page to enable lazy loading will offset any potential gain you get from it.

Chapter 5: Lazy Loading’s Dependency on JavaScript

The entire idea of lazy loading is dependent on JavaScript being enabled and available in the user’s browser. While most of your users will likely have JavaScript enabled, it is essential to plan for cases where it is not.

You could either show a message telling users why the images won’t load and encourage them to either use a modern browser or enable JavaScript.

Another route is to use the noscript tag. However, this approach comes with some gotchas. This question thread on Stack Overflow does a great job addressing these concerns and is a recommended read for anyone looking to address this set of users.

Chapter 6: Popular JavaScript Libraries for Lazy Loading

Since environments and implementation details can vary across browsers and devices, you might want to consider a tried and tested library for lazy loading rather than spinning something up from scratch.

Here is a list of popular libraries and platform specific plugins that will allow you to implement lazy loading with minimal effort:

  • Yet Another Lazy Loader: This library uses the Intersection Observer API and falls back to event-based lazy loading for browsers that do not yet support it. This is great for just about any HTML element but unfortunately does not work on background images in CSS. The good news is that it supports IE back to version 11.
  • lazysizes:?This is a very popular library with extensive functionality. It includes support for responsive image srcset and sizes attributes and provides superb performance even though it does not make use of the Intersection Observer API.
  • WordPress A3 Lazy Load: There are plenty of lazy loading WordPress plugins out there, but this one comes with a robust set of features, including a fallback when JavaScript is unavailable.
  • jQuery Lazy: A simple library that uses a jQuery implementation.
  • WeltPixel Lazy Loading Enhanced:?A Magento 2 extension.
  • Magento Lazy Image Loader:?Another Magento extension, for 1.x.
  • Shopify Lazy Image Plugin (paid): Enable lazy loading on a Shopify site.
Chapter 7: Testing Lazy Load

Once you have implemented lazy loading, you will likely want to check that it’s working as intended. The simplest way would be to open up the developer tools in your browser.

From there, go to Network > Images. When you refresh the page for the first time, you should only see loaded images in the list.

Then, as you start scrolling down the page, other image load requests would get triggered and loaded. You can also notice the timings for image load in the waterfall column in this view. It would help you identify image loading issues if any or issues in triggering the image load.

Another way would be to run the Google Chrome Lighthouse audit report on your page after you have implemented the changes and look for suggestions under the “Offscreen images" section.


We have covered a lot of ground about lazy loading images! Lazy loading—if implemented well—can have significant benefits on your site’s performance the loading performance while reducing the overall page size and delivery costs, thanks to deferring unnecessary resources up front.

So, what are you waiting for? Get started with lazy loading images now!

The post The Complete Guide to Lazy Loading Images appeared first on CSS-Tricks.

Control the Internet With Chrome Extensions!

Css Tricks - Mon, 09/24/2018 - 4:03am

As a web UI developer and designer, there are countless things to learn and only so many hours in the day. There are topics I’ve purposefully avoided, like mobile and offline application development because, at some point, you have to draw a line somewhere in the millions of shiny new topics and get some work done. One of the areas I’ve avoided in the past is browser extension development. I didn’t understand how they worked, what the development environment was, or how permissions interacted with overriding pages because, frankly, I didn’t think I was interested.

Then one day, my very talented designer/developer friend Natalie Schoch asked me to get her Chrome Extension across the finish line. She had the front-end prototyped, but needed some help plugging in the data set and with interactive JavaScript. The project is called Wordsmith and it’s out now at the Chrome Extension Store. It’s a free and aesthetically pleasing way to learn new vocabulary as you browse the web. The extension surfaces a new vocabulary word, along with its definition and synonyms in each new tab.

Anyway, enough plugging the new thing we made and on to the fun of figuring out Chrome Extensions!

An animation showing how the Wordsmith extension works when you open a new tab in Chrome.

First, what is a Chrome Extension anyway? According to the Chrome developer docs:

Extensions are event based programs used to modify or enhance the Chrome browsing experience. They enable users to tailor Chrome functionality and behavior to individual needs or preferences. They are built on web technologies such as HTML, JavaScript, and CSS.

(Emphasis mine)

Basically, a Chrome Extension is a one-trick pony tool built on top of the normal browsing experience to override a focused set of interactions.

Getting a bare-bones extension up and running

The Chrome docs are mostly straightforward but can get overly complicated for a beginner. The first thing you need to make in your local project directory is a manifest.json file. This file functions as the command center for your extension. This is where you will tell Chrome what files it should be paying attention to and what type of extension logic you are using.

{ “version”: 1.0:, // This is your regular project version number “manifest_version”: 2, // Just use 2, it's the stable version you want “name”: “Wordsmith”, // The name of your extension! “description”: “New tab? New word!”, // The description of your extension! “author”: “Natalie Schoch and Lindsay Grizzard”, // Who you are “chrome_url_overrides” : { “newtab”: “newtab.html” } }

Let’s talk about that chrome_url_overrides bit. This is telling Chrome, “Hey, that thing you would normally load (in this case) in a new tab, load this cool thing I made instead.” I recommend starting with a new tab Chrome extension because it is the quickest way to see that you are getting this little extension thing to work. You could also override history or bookmarks, but I’ll let you explore that on your own.

Now we can create a new file called newtab.html:

<!DOCTYPE HTML> <html> <body> <h1> Hey there world </h1> </body> </html>

Great! Now all you have to do is load this into Chrome’s extension developer system to see your beautiful work. To get this up and running, load your project into Chrome’s developer mode with the following steps:

  1. Go to chrome://extensions
  2. Turn on "Developer Mode" in the top right
  3. Click "Load Unpacked"
  4. Load the directory containing your manifest.json and newtab.html files
  5. Open a new tab!

You should see this magic:

You just built a Chrome Extension. Congrats! At this point, you can go on your own adventure and make any static design for a new tab. You can write CSS as you normally would (set up SCSS compiling, script tags, inline if you are a monster, etc…), and create new static things.

The most important thing to remember when changing the manifest.json file or JS files is that you must go back into chrome://extensions and hit the reload icon for your extension. It will not update from your local development automatically and your changes will not be reflected without this step. This confused the heck out of me.

Now let’s talk about JavaScript

There are two types of script files in Chrome Extensions: content scripts and background scripts.

Background scripts are used for handling central application tasks. They can act like a controller for your application, staying dormant until an event fires and unloading after the event completes. Use background scripts when you want to control the core logic of your application or listen for interactions that are outside of the page’s DOM. An example would be clicking your Chrome extension’s icon in the top right of the toolbar. That isn’t part of the page-specific DOM. If you want to manipulate things outside of the sandboxed page you are on, you will need background scripts.

Clicking the icon and having a popup load is an example of a background script command.

As a note, these rely on the Chrome API and are a bit more advanced. In Wordsmith, I decided to forgo background scripts completely as we only needed DOM-specific UI. I found background scripts particularly tricky and got the most help from Daniel Shiffman’s video tutorial. In fact, his whole tutorial series is a lovely introduction to extension development.

Content scripts execute JavaScript in the context of a specific webpage and in isolation. This means each script can access the current DOM and manipulate it, but the DOM and its scripts, cannot manipulate the Chrome extension in return. Content scripts have limited Chrome API access and exist to work in single, isolated instances. This secures extension information and halts library conflicts.

Cool, but what does all that actually mean? It says two things. You can use content scripts to perform regular browser JavaScript, as you would in a simple web application. The isolation definition means your extension’s JavaScript is in it's own universe, separate from any webpage's JavaScript. This keeps things like API secret keys private from page scripts. It also let’s you use any version of a JavaScript library in your extension without worrying about conflicting versions on a given webpage.

The practical difference in using content scripts is how they are loaded. Instead of linking directly to the file in HTML, use the manifest.json file to indicate the scripts you would like to call.

{ “manifest_version”: 2, “name”: “Wordsmith”, “description”: “New tab? New word!” “author”: “Natalie Schoch and Lindsay Grizzard”, “chrome_url_overrides” : { “newtab”: “newtab.html” }, "content_scripts": [ { "matches": [ "<all_urls>" //see all match pattern options in the chrome docs ], "js": ["[your-path-to]/jquery.min.js","[your-path-to]/scripts.js"] } ] }

This new content script command in the manifest.json file tells Chrome a few things. It tells Chrome where you want that file to run with the “matches” statement. Do you want it to load on every single Chrome page? Are you making an extension that should only affect certain pages? To specify this, add the appropriate URL match pattern to tell Chrome what to pay attention to. It also tells the manifest file where to find your content scripts and in what order to execute them.

When changing the manifest.json file or JavaScript files is that you must go back into chrome://extensions and hit the reload icon for your extension.

Add a console.log() to your new script file, reload your extension, navigate to any URL, and you will see your console message. Seeing the console log tells you that you now have access to the DOM and can start manipulating it. CHROME EXTENSIONS ARE SO COOL. You have the power to play around with the front-end of the internet without needing source code or a complex dev environment. Now let’s have some fun by making all the divs on a page red!


Now, go to another website. Everything is awful and red, but you have so much power! You can manipulate any webpage to do your bidding. Go forth and mold the design of the internet into something better (or worse) for yourself or others!

That’s basically everything you need to know to get started with Chrome Extensions. Although the documentation can be a little foreign at first, start with a simple static new tab extension and iterate from there!

Happy manifest(.json)ing!

Check out Wordsmith’s GitHub repo to see how we built out our first Chrome Extension and feel free to fork and let us know about bugs!

The post Control the Internet With Chrome Extensions! appeared first on CSS-Tricks.

Having fun with link hover effects

Css Tricks - Fri, 09/21/2018 - 4:39am

A designer I work with was presenting comps at a recent team meeting. She had done a wonderful job piecing together the concept for a design system, from components to patterns and everything in between that would make any front-end developer happy.

But there was a teeny tiny detail in her work that caught my eye: the hover state for links was a squiggle.

Default link (top) and hover effect (bottom)

Huh! Not only had I not seen that before, the idea had never even crossed my mind. Turns out there are plenty of instances of it on live sites, one being The Outline. That was the one that was implementation that inspired the design.

Cool, I figured. We can do something like a linear background gradient or even a background image. But! That wasn't the end of the design. Turns out it's animated as well. Again, from The Outline:

Screenshot from The Outline article (source)

Whoa! That's pretty wild. I wasn't sure how to approach that, honestly, because animating any of my initial ideas would be difficult, especially for cross-browser support.

So, how did The Outline do it? Turns out, it's SVG. We can make a squiggly path and animate it pretty easily:

See the Pen Squiggle by Geoff Graham (@geoffgraham) on CodePen.

But how does that work with a link? Well, we can use SVG on the background-image property:

See the Pen Squiggle by Geoff Graham (@geoffgraham) on CodePen.

But that's kinda crappy because we can't really animate that. We need better values for that. However, we can inline CSS directly on the SVG in the background-image property. We can't simply copy and paste the SVG code into the property, but we can with some proper encoding:

See the Pen Squiggle by Geoff Graham (@geoffgraham) on CodePen.

And, since SVG can contain its own styles within the markup, the animation can be tossed right there in the background-image property, the same way we would do it with CSS in an HTML document head or inline CSS in HTML.

See the Pen Squiggle by Geoff Graham (@geoffgraham) on CodePen.

We can style it up a little differently, if we'd like:

See the Pen Link Effectz - Squiggle by Geoff Graham (@geoffgraham) on CodePen.

This is inspiring!

I have no idea if an animated squiggle makes for a good user experience and, frankly, that's not the point of this post. The point is that The Outline had a fun idea with a slick CSS implementation.

That got me thinking about other non-standard (perhaps even unconventional) hover styling we can do with links. Again, tossing aside usability and have a grand ol' time with CSS...

The Border to Background Effect

Maybe that same bottom border on the default link can grow and become the full background of the link on hover:

See the Pen Link Effectz - Background on hover by Geoff Graham (@geoffgraham) on CodePen.

Heck, we can even do something similar horizontally:

See the Pen Link Effectz - Horizotonal Background by Geoff Graham (@geoffgraham) on CodePen.

The Outlined Text Effect

Let's strip out the font color and leave an outline behind.

See the Pen Link Effectz - Outline on hover by Geoff Graham (@geoffgraham) on CodePen.

The Raised Text Effect

Another idea is to raise the text as if it grows out of the page on hover:

See the Pen Link Effectz - Raised text on hover by Geoff Graham (@geoffgraham) on CodePen.

The Font Swapper-oo Effect

This is so impractical that it makes me LOL, but why not:

See the Pen Link Effectz - Swap font on hover by Geoff Graham (@geoffgraham) on CodePen.

The "Turn it Up, Chris" Effect

Sorry, Chris. You know you love it. ❤️

See the Pen Link Effectz - Turn it up, Chris! by Geoff Graham (@geoffgraham) on CodePen.

What can you come up with?

Have ideas? Let me know in the comments and I'll toss 'em in the CodePen collection I've started.

The post Having fun with link hover effects appeared first on CSS-Tricks.

Safari Ripper ??

Css Tricks - Thu, 09/20/2018 - 8:36am

Security researcher Sabri posted a bit of code that will "force restart any iOS device." It's interesting to see HTML & CSS have this kind of dangerous power. It's essentially a ton of <div>s scaled to be pretty huge and then set over a repeating JPG image with each <div> blurring the background via backdrop-filter. It must cause such extreme and unhandled memory usage that it wreaks havoc on the browser as well as the entire operating system.

I was trying to test it out myself and be really careful not to execute it... but of course I did, and it crashed my Chrome 68 on a MacBook Pro. Not the whole operating system, but I had to force quit the browser. Then again, I suppose even while(true) {} can do that!

The comment thread on the gist hast more interesting details, like how it crashes iOS Safari 9+ (including the new version 12!) and weird behavior on the PlayStation 3 native browser.

Direct Link to ArticlePermalink

The post Safari Ripper ☠️ appeared first on CSS-Tricks.

All Fired Up About Specificity

Css Tricks - Thu, 09/20/2018 - 3:54am

You never know where the next Grand Debate™ in front-end is going to come from! Case in point: we just saw one recently based on a little Twitter poll by Max Stoiber in which 57% of people got it wrong. There were reactions ranging from the innocuous hey fun a little brain teaser! to the state of web education is in shambles and beyond.

I heard from a number of folks that they just felt sad that so many people don't know the answer to a fairly simple question. To be fair, it was (intentionally, I'm sure) rather tricky! It wasn't really a question about CSS — it was more about the idea that the order of HTML attributes doesn't matter. It's the order of CSS that does.

One extreme response I saw said that front-end stuff like this is needlessly complicated and getting it wrong is almost a point of pride. This sentiment was so strong that I heard it suggested that people who know the answer have filled their brains with useless information and that somehow makes them a worse developer. Equally extreme were suggestions that writing HTML and CSS raw like that should always be avoided in favor of tooling abstractions to "fix" these "problems."

(Excuse the quotes there, I'm not trying to pick a side so much as to emphasize that not everyone considers these problems that need to be fixed.)

Another take was that the vibe would be different if something similar happened in JavaScript-land. The perception is that it's embarrassing or bad not to know JavaScript basics, but not knowing HTML and CSS basics is the fault of the language, or that the value of knowing it is not worth bothering to understand.

At the same time, this poll became the perfect mirror to see the strong opinions people have about front-end practices. Fascinating, really.

Here are a few more takes from folks who chimed from their own blogs:

Keith Grant:

I hate that this has somehow become some “old guard” vs. “new guard” thing.

The problem with drawing lines like this: whichever side you find yourself on, there are some whackos out there throwing ridiculous arguments into the mix. And now people on the other side associate that viewpoint with you.

Tim Kadlec:

It doesn’t bother me too much that people are getting the question wrong. Everyone is at different stages in their career and everyone has different problems they’re facing in their daily tasks, so sure, not everyone is going to know this yet.

I do find it a bit alarming just how many folks got it wrong though.

John Allsopp:

One the one hand (and this will somewhat simplify each ‘side’, for the sake of brevity, not disrespect to either), we have those, and I’d on balance probably include myself in this camp, who’d argue that the core technologies of the Web are precisely that–foundational, and a deep understanding of them conceptually (not necessarily an encyclopedic knowledge of every syntactic aspect) is fundamental working knowledge for professional Web developers.

Kevin Ball:

With the growth of the importance of front-end development, we're seeing the story play out again.

The systematic devaluation of CSS, and more, the people who use CSS.

The constant "mansplaining" of CSS features to women who literally are the reason it exists.

Conference speakers asked questions about whether "there is any value in people who cannot write JavaScript?".

All of this at a time when CSS is improving faster than ever and enabling dramatic changes in web design.

This isn't about better technology, it's about exclusion.

Have you seen any other takes or have any of your own?

The post All Fired Up About Specificity appeared first on CSS-Tricks.

Introducing the YOOtheme Pro Page Builder

Css Tricks - Thu, 09/20/2018 - 3:50am

(This is a sponsored post.)

YOOtheme Pro is a powerful theme and page builder developed by YOOtheme that provides a new experience of building websites in WordPress. Designers will get an easy and exciting way to design and create websites due to premium layouts and an intuitive page builder, and developers will especially appreciate its extendability and clean and semantic code. YOOtheme has been known as a leading theme provider for over 10 years, and now with YOOtheme Pro they created the next page builder to be watched for on the WordPress market.

The Page Builder

If you are familiar with WordPress, YOOtheme Pro is a perfect choice for you since it is seamlessly integrated into the native WordPress customizer. You can easily create your layouts by dividing your content into sections, rows and grids. And thanks to the drag and drop interface, you can design beautiful responsive page layouts without even having to code. All your changes will be instantly shown in live preview.

Arrange Your Content With Ease

YOOtheme Pro has a growing library of over 30 content elements. Here you can find both common elements like the Video, Panel, Image or Heading, but you can also expect some advanced elements such as the Slider, Slideshow or Gallery with the masonry effect and filter option and even more. YOOtheme Pro also allows you to place WordPress widgets anywhere in your layout. All elements are built with the popular front-end framework UIkit that provides modern codebase with fast and sleek JavaScript.

Sophisticated Layouts for Your Website

YOOtheme invests a lot of time and effort into the development of their layouts. A team of professional designers regularly creates complete website concepts with a thought-out content structure and focus on modern design trends. They already have over 100 layouts with free-to-use images and even hand-made illustrations that can be found in the Layout Library. You can filter layouts according to topics and types, mix and match them, save your own layouts to reuse them later. This provides you with unlimited possibilities and makes creating websites in WordPress as easy as can be.

A Library of Over 70 Beautiful Styles

What makes YOOtheme Pro stand out even more is the Style Library that includes over 70 handcrafted styles. One click, and the look of your website changes completely. Whether you are looking for a minimalistic or a bold style, this substantial collection represents all trends. You can customize next to anything with YOOtheme Pro, from changing the style of each item separately to applying changes globally. This gives you all the power to style your WordPress website with none of the coding.

Integrated Unsplash Image Library

The popular Unsplash library that provides quality and free-to-use photos is seamlessly integrated into YOOtheme Pro. Due to this integration you can search through the library and try out images directly on your website without having to leave YOOtheme Pro. Use filter, browse through collections and users and insert images directly into your layouts. The images will only be downloaded after your click Save. This feature is a real time-saver for every designer.

Lightning-fast and Developer-friendly

YOOtheme Pro is a true piece of German engineering, it is fast, lightweight and easy like no other page builder. Powered by Vue.js and Uikit, it provides a great user experience. YOOtheme Pro also cares about speed. The small code size as well as the latest web technologies ensure the first meaningful paint gets quickly on the screen. And with auto-generated srcsets, lazy loading images and next-gen image formats like WebP YOOtheme Pro will boost the Google PageSpeed rank for your WordPress website. What's more, Google Fonts are stored locally, which saves the request to Google and ensures GDPR compliance.

A modular and extendable architecture makes YOOtheme Pro extremely developer-friendly. It allows you to override everything, add custom elements, CSS, JavaScript and new themes settings. An extensive documentation including video tutorials and a section specifically written for developers will help you get started in no time.

Get YOOtheme Pro

YOOtheme Pro both simplifies and empowers website building. Regular release of theme packages including sophisticated layouts on a specific topic, six style variations and free-to-use images will make YOOtheme Pro the only thing you'll need to create a website. And while we could talk more about how YOOtheme Pro supports WooCommerce and has a a Footer Builder and many desktop and mobile header layouts, we'd rather let you see for yourself. Get YOOtheme Pro and experience the future of website building today.

Direct Link to ArticlePermalink

The post Introducing the YOOtheme Pro Page Builder appeared first on CSS-Tricks.

Using Scoped Slots in Vue.js to Abstract Functionality

Css Tricks - Wed, 09/19/2018 - 3:47am

Let’s start with a short introduction to Vue.js slots concept. Slots are useful when you want to inject content in a specific place of a component. Those specific places that you can define are called slots.

For example, you want to create a wrapper component that is styled in a specific way but you want to be able to pass any content to be rendered inside that wrapper (it might be a string, a computed value, or even another component).

There are three types of slots:

  • default / unnamed slots: used when you have a single slot in a component. We create them by adding <slot> in the template where we want to be able to inject our content. This <slot> tag will be replaced with any content passed to the component’s template.
  • named slots: used when you have multiple slots in a component and we want to inject different content in different places (slots). We create those by adding <slot> with a name attribute (e.g. <slot name="header"></slot>). Then when we render our component, we provide a slot content for each named slot by adding a slot attribute with the slot name.
<base-layout> <template slot="header"> <h1>My awsome header</h1> </template> <template slot="footer"> <p>My awsome footer</p> </template> </base-layout>

By doing that, the <slot> tags in the component will be replaced by content passed to the component.

  • scoped slot: used when you want a template inside a slot to access data from the child component that renders the slot content. This is particularly useful when you need freedom in creating custom templates that use the child component’s data properties.
Real-World Example: Creating a Google Map Loader component

Imagine a component that configures and prepares an external API to be used in another component, but is not tightly coupled with any specific template. Such a component could then be reused in multiple places rendering different templates but using the same base object with specific API.

I’ve created a component (GoogleMapLoader.vue) that:

  1. initializes the Google Maps API
  2. creates google and map objects
  3. exposes those objects to the parent component in which the GoogleMapLoader is used

Below is an example of how this can be achieved. We will analyze the code piece-by-piece and see what is actually happening in the next section.

Let’s first establish our GoogleMapLoader.vue template:

<template> <div> <div class="google-map" data-google-map></div> <template v-if="Boolean( && Boolean("> <slot :google="google" :map="map" /> </template> </div> </template>

Now, our script needs to pass some props to the component which allows us to set the Google Maps API and Map object:

import GoogleMapsApiLoader from "google-maps-api-loader"; export default { props: { mapConfig: Object, apiKey: String }, data() { return { google: null, map: null }; }, async mounted() { const googleMapApi = await GoogleMapsApiLoader({ apiKey: this.apiKey }); = googleMapApi; this.initializeMap(); }, methods: { initializeMap() { const mapContainer = this.$el.querySelector("[data-google-map]"); = new, this.mapConfig); } } };

This is just part of a working example. You can dive in deeper this example.

OK, now that we have our use case set up, let’s move onto breaking that code down to explore what it’s doing.

1. Create a component that initializes our map

In the template, we create a container for the map which will be used to mount the Map object extracted from the Google Maps API.

// GoogleMapLoader.vue <template> <div> <div class="google-map" data-google-map></div> </div> </template>

Next up, our script needs to receive props from the parent component which will allow us to set the Google Map. Those props consist of:

  • mapConfig:?Google Maps config object
  • apiKey:?Our personal api key required by Google Maps
// GoogleMapLoader.vue import GoogleMapsApiLoader from "google-maps-api-loader"; export default { props: { mapConfig: Object, apiKey: String },

Then, we set the initial values of google and map to null:

data() { return { google: null, map: null }; },

On the mounted hook, we create an instance of googleMapApi and the map object from it. We also need to set the values of google and map to the created instances:

async mounted() { const googleMapApi = await GoogleMapsApiLoader({ apiKey: this.apiKey }); = googleMapApi; this.initializeMap(); }, methods: { initializeMap() { const mapContainer = this.$el.querySelector("[data-google-map]"); = new, this.mapConfig); } } };

So far, so good. With all that done, we could continue adding the other objects to the map (Markers, Polylines, etc.) and use it as an ordinary map component.

But, we want to use our GoogleMapLoader component only as a loader that prepares the map — we don’t want to render anything on it.

To achieve that, we need to allow the parent component that will use our GoogleMapLoader to access and that are set inside the GoogleMapLoader component. That’s where scoped slots really shine. Scoped slots allow us to expose the properties set in a child component to the parent component. It may sound like an inception, but bear with me one more minute as we break that down further.

2. Create component that uses our initializer component

In the template, we render the GoogleMapLoader component and pass props that are required to initialize the map.

// TravelMap.vue <template> <GoogleMapLoader :mapConfig="mapConfig" apiKey="yourApiKey" /> </template>

Our script tag should look like this:

import GoogleMapLoader from "./GoogleMapLoader"; import { mapSettings } from "@/constants/mapSettings"; export default { components: { GoogleMapLoader, }, computed: { mapConfig() { return { ...mapSettings, center: { lat: 0, lng: 0 } }; }, } };

Still no scoped slots, so let’s add one.

3. Expose google and map properties to the parent component by adding a scoped slot

Finally, we can add a scoped slot that will do the job and allow us to access the child component props in the parent component. We do that by adding the <slot> tag in the child component and passing the props that we want to expose (using v-bind directive or :propName shorthand). It does not differ from passing the props down to the child component, but doing it in the <slot> tag will reverse the direction of data flow.

// GoogleMapLoader.vue <template> <div> <div class="google-map" data-google-map></div> <template v-if="Boolean( && Boolean("> <slot :google="google" :map="map" /> </template> </div> </template>

Now, when we have the slot in the child component, we need to receive and consume the exposed props in the parent component.

4. Receive exposed props in the parent component using the slot-scope attribute

To receive the props in the parent component, we declare a template element and use the slot-scope attribute. This attribute has access to the object carrying all the props exposed from the child component. We can grab the whole object or we can de-structure that object and only what we need.

Let’s de-structure this thing to get what we need.

// TravelMap.vue <template> <GoogleMapLoader :mapConfig="mapConfig" apiKey="yourApiKey" > <template slot-scope="{ google, map }"> {{ map }} {{ google }} </template> </GoogleMapLoader> </template>

Even though the google and map props do not exist in the TravelMap scope, the component has access to them and we can use them in the template.

Yeah, OK, but why would I do things like that? What is the use of all that?

Glad you asked! Scoped slots allow us to pass a template to the slot instead of a rendered element. It’s called a scoped slot because it will have access to certain child component data even though the template is rendered in the parent component scope. That gives us a freedom to fill the template with custom content from the parent component.

5. Create factory components for Markers and Polylines

Now, when we have our map ready, we will create two factory components that will be used to add elements to the TravelMap.

// GoogleMapMarker.vue import { POINT_MARKER_ICON_CONFIG } from "@/constants/mapSettings"; export default { props: { google: { type: Object, required: true }, map: { type: Object, required: true }, marker: { type: Object, required: true } }, mounted() { new{ position: this.marker.position, marker: this.marker, map:, icon: POINT_MARKER_ICON_CONFIG }); }, }; // GoogleMapLine.vue import { LINE_PATH_CONFIG } from "@/constants/mapSettings"; export default { props: { google: { type: Object, required: true }, map: { type: Object, required: true }, path: { type: Array, required: true } }, mounted() { new{ path: this.path, map:, ...LINE_PATH_CONFIG }); }, };

Both of these receive google that we use to extract the required object (Marker or Polyline) as well as map which gives as a reference to the map on which we want to place our element.

Each component also expects an extra prop to create a corresponding element. In this case, we have marker and path, respectively.

On the mounted hook, we create an element (Marker/Polyline) and attach it to our map by passing the map property to the object constructor.

There’s still one more step to go...

6. Add elements to the map

Let’s use our factory components to add elements to our map. We must render the factory component and pass the google and map objects so data flows to the right places.

We also need to provide the data that’s required by the element itself. In our case, that’s the marker object with the position of the marker and the path object with Polyline coordinates.

Here we go, integrating the data points directly into the template:

// TravelMap.vue <template> <GoogleMapLoader :mapConfig="mapConfig" apiKey="yourApiKey" > <template slot-scope="{ google, map }"> <GoogleMapMarker v-for="marker in markers" :key="" :marker="marker" :google="google" :map="map" /> <GoogleMapLine v-for="line in lines" :key="" :path.sync="line.path" :google="google" :map="map" /> </template> </GoogleMapLoader> </template>

We need to import the required factory components in our script and set the data that will be passed to the markers and lines:

import { mapSettings } from "@/constants/mapSettings"; export default { components: { GoogleMapLoader, GoogleMapMarker, GoogleMapLine }, data() { return { markers: [ { id: "a", position: { lat: 3, lng: 101 } }, { id: "b", position: { lat: 5, lng: 99 } }, { id: "c", position: { lat: 6, lng: 97 } } ], lines: [ { id: "1", path: [{ lat: 3, lng: 101 }, { lat: 5, lng: 99 }] }, { id: "2", path: [{ lat: 5, lng: 99 }, { lat: 6, lng: 97 }] } ] }; }, computed: { mapConfig() { return { ...mapSettings, center: this.mapCenter }; }, mapCenter() { return this.markers[1].position; } } }; And we’re done!

With all those bits and pieces completed, we can now re-use the GoogleMapLoader component as a base for all our maps by passing different templates to each one of them. Imagine that you need to create another map with different Markers or just Markers without Polylines. By using a pattern of scoped slots, it becomes very easy since all we need to pass now is different content to the GoogleMapLoader component.

This pattern is not strictly connected to Google Maps; it can be used with any library to set the base component and expose the library’s API that might then be used in the component that summoned the base component.

It might be tempting to create a more complex or robust solution, but this gets us the abstraction we need and it becomes an independent piece of our codebase. If we get to that point, then it might be worth considering extraction to an add-on.

The post Using Scoped Slots in Vue.js to Abstract Functionality appeared first on CSS-Tricks.

Twenty Years as a Freelance Web Developer: Wisdom Gained and Lessons Learned

Css Tricks - Tue, 09/18/2018 - 3:50am

In the summer of 1998, when President Clinton fended off allegations of sexual impropriety and Donald Trump filmed a cameo in a Woody Allen movie, I embarked on my career as a freelance web developer. Twenty years and more than 300 websites later, I’m still at it—always working on my own and always from home. Over that time, I’ve had the pleasure of partnering with many prominent advertising agencies and boutique design firms as well as scores of local businesses and individuals.

Those interested in making the switch to freelancing have often asked me for advice, and I’ve been happy to help with whatever words of wisdom I can provide. This article is a distillation of much of that. And it may prove helpful not only to developers and programmers who wish to freelance, but also designers, project managers, copywriters—anyone who desires to work independently from home in our industry. It’s a career path that I have loved, but it’s not for everyone.

My background

None of this was planned. I did have a teenage interest in programming, first learning BASIC on the Timex Sinclair 1000 and then Assembly Language on the Apple II. Despite this, after graduating college, I pursued a career on the business side of magazine publishing. Less than six years later, however, I needed a change, and my path took me to Pratt Institute in New York where I enrolled in a graphic design program. This included electives in HTML and JavaScript that unexpectedly rekindled my desire to program. A teacher then referred me to a recruiter and my new career as a freelance front-end developer was born.

The primary element of successful freelancing

When I’m asked the more existential question of how I’ve survived so long as a freelancer, my response is always the same: above all, be reliable. Don’t get me wrong; it’s important that my delivered websites work as promised—requirements must be met and best practices followed. But I quickly found that my clients were not necessarily looking for perfection in the work itself. In fact, to this day, I often have the odd feeling that no one even looks at my code as long as there aren’t any bugs.

What really matters is delivering on time. Deadlines are sacrosanct. If project managers, who seem perpetually overworked and under pressure, can depend on me to keep to a schedule, that’s one less part of their overall responsibilities to keep them up at night. For that, I’m routinely thanked. My creative use of CSS or efficient JavaScript coding? Rarely is that even acknowledged.

Achieving this kind of reliability ends up being the primary challenge for a freelancer, especially when juggling multiple projects for multiple clients. Then there’s the additional stress of knowing that there’s no one to step in during sickness or emergencies. My go-to sports metaphor is that working as part of a group is like being on a basketball team. Having a poor shooting night? Dish the ball off to one of your teammates to pick up the slack. A freelancer working from home is more like a boxer—you’re alone in the ring with no one else to take credit or assume blame. Throwing in the towel is not an option.

Inevitably, though, there will be issues that can affect a freelancer’s ability to be reliable. Delays occur, scopes change, deadlines shift. That’s when open and honest communication with the client is necessary. In earlier days, I feared that I wouldn’t be hired for future projects if I rocked the boat in any way. In reality, though, I have found quite the opposite to be true. If the best interests of the project and its processes are kept in mind, I believe clients appreciate when red flags are pointed out, as difficult as those conversations may be. Being a successful freelancer is not the same as one who is excessively pliant. One must be proactive in voicing concerns that may affect his or her role on any project.

Be the generalist who specializes

My specialty is front-end development. Clients hire me to take beautiful designs and translate them into code that works in everyone’s browsers. To do this, I’ve had to master HTML, CSS, and JavaScript. Despite having marketable knowledge in related areas, including Flash when it was popular and now WordPress, my core expertise remains unchanged. And it’s this core expertise that gets me work.

This is important because I have found that most projects for which I’m hired as a freelancer, particularly the larger ones, resemble an assembly line—different individuals are tasked to complete one specific part of the process while working alongside others doing the same. Ultimately, everything is assembled into the final product. It’s in these instances when I’m utilizing that one skill that I’m expected to do very well. That I possess much ancillary knowledge is irrelevant.

As I’m sure everyone has noticed, the descriptives "full stack developer" and "full stack designer" have gained prominence of late. In earlier days, we simply referred to these individuals as having a broad skill set in their discipline. Whatever the terminology, having a wide swath of knowledge is certainly a huge plus and can only serve to extend one’s career, but bear in mind that it’s important to have that one defined skill that you do better than most. The freelancer who is the proverbial jack of all trades and master of none is not often seen as enticing to hire.

The myth of diversification

My perception early on was that being a freelancer would provide more financial security than the alternative. Instead of having all my eggs in the one basket of a permanent employer, I expected to spread the risk among a roster of clients. There would always be someone to pick up the slack if any one of them flew the coop.

In practice, though, I have found this to be an unsustainable model as it’s simply not possible to satisfy all requests for your services during peak times—there’s only so much work any of us can handle at once. This results in some clients necessarily forced to look elsewhere to staff their projects. Then, the next time around, you may no longer be at the top of their resource list of freelancers.

This contributes to the inevitable equilibrium where one or two clients emerge to represent well more than half of my business. I’ve seen this dynamic play out again and again, no matter the ups and downs of the economy and demand for my services. The smaller, less-frequent clients are there for when I’m otherwise available but are not my priority. On the bright side, having primary clients who hire me on a regular basis provides a dependable source of income; the negative is that I’m rarely as diversified as I once hoped I would be.

Homebound networking

So how does one obtain work in the first place? After using a recruiter early on, which, for me, was particularly necessary since I lacked any relevant experience, my network expanded as people with whom I had worked inevitably moved on to new employers. These contacts, most often designers and project managers, kept me in their virtual Rolodex as a potential resource, thus growing my network.

My other significant channel for leads has been from the simple act of meeting people in everyday life and sharing with them what I do for a living. These casual conversations —even with those who seemingly had no need for my services—often create serendipitous opportunities that lead to new work. As the saying goes, it’s not the people you know, but the people they know. Don’t be shy—tell the world what you do to help generate word-of-mouth referrals. You are your own greatest advocate.

While LinkedIn serves as a useful conduit for exposure, it’s the freelancer’s own website that provides the best and most-controlled opportunity to show who you are and what you do. But, as someone who has consulted with clients in hiring decisions, I have seen so many of these websites obscure the very information necessary to make such a choice. Avoid the temptation of making the website itself a demonstration of one’s skills. Eschew needless animations or distractions. It’s best to keep key information, such as the portfolio and resume, easy to find and, yes, even to print.

Of course, the more repeat business one can secure, the less need there is to obtain new clients. I believe the personal relationships I have sought to cultivate are what have helped me with this. By meeting with key contacts in person, unspoken bonds are formed that lead to genuine partnerships, transcending traditional employer/contractor interactions. In the age of Skype and Slack, the freelancer working from home can go long stretches without any direct face-to-face communication with those for whom they are working. If logistically possible, one must move past the screen and make an impression in the real world.

Show me the money!

There’s no question that my least favorite part of freelancing is the constant need to submit estimates. In fact, I tend to look at it as a no-win situation. If my estimate is readily accepted, there’s a shallow feeling that I’ve left money on the table; if a client responds in disbelief that I asked for so much, I feel a sense of shame that I’ve greatly overreached. But there’s a misplaced fear that by asking for too much, the client will be offended and walk away. That’s never happened to me. If anything, apologies are offered and negotiations commence.

Always remember, though, that your work has value and deserves to be compensated appropriately at market rates. By significantly underbidding estimates, which is always a temptation when work is slow, it implies to a client that you don’t value your own work. On those rare occasions when I’ve made the mistake of selling myself short, I tend to work on those projects "angry"—not at the client, but at myself for being placed in a situation where I must invest more time for less money.

The invoice has been submitted and paid. Then what? Many prominent financial advisors recommend keeping a three- to six-month reserve fund for emergencies. What I say is that, as a freelancer, you can never save enough. Booms and busts are common in the modern economy and seem to happen with greater frequency. Therefore, save and then save some more. I’ve endured two major economic downturns—the collapse of the dot-com bubble in 2001 and the Great Recession of 2008. Each time, my income essentially dried up for a lengthy duration. Having enough savings set aside enabled me to ride out the storm.

Maintaining a work/life balance

Much has been written lately about the mental health challenges faced by those who work in our industry. Most of us go through various stages of our career when, at times, the stresses of one’s professional and personal experiences can take their toll. I have not been immune to this. As my career progressed, the care-free mindset of youth was gradually supplanted by concerns of where my life was headed. Self-confidence became self-doubt. I don’t see this necessarily as a manifestation unique to our industry, but simply the result of being a human being in modern society.

Working from home as a freelancer can make matters worse. In the relative isolation of a home office, it’s easy to slip into a downward spiral without having others nearby to offer encouragement. When the time came, it was my responsibility to make a concerted effort to reach out to my clients and friends (often one and the same) for support. People can relate and empathize. We are not alone in our struggles.

What helps most in keeping myself balanced is getting away from the computer, or any video screen for that matter, as often as possible. Regardless of workload, I make sure to take trips to the gym, visit friends, or simply go for a walk. I also frequently take classes that have nothing to do with my career to stimulate different parts of my brain. Right now, I’ve dedicated a significant amount of free time to learning German, which is a welcome challenge wholly unrelated to web development.

When teaching yourself something new related to work, try creating projects that are both rewarding and challenging. To keep motivated, pretend to be your own client and set deadlines and milestones. Last year, I did just that and developed a jQuery plugin, which I wrote about for CSS-Tricks, that allows the browser to read webpages aloud. It was a terrific learning experience, and I had fun along the way.

Moving forward

These have been my own reflections on a freelance career that’s closer to its end than its beginning. Others with a similar career history may have different impressions and advice—the comments section below is a terrific forum for voicing any corroborating or contrasting opinions.

As with any career path, being a freelancer has embodied its own set of rewards and sacrifices. And while my regrets are few, those who consider freelancing will have to decide for themselves whether it’s right for them. The liberating part of making that decision is that there really is no "right" answer. We are all different, always changing, ever evolving. What didn’t work for us professionally ten years ago may feel perfectly appropriate at a later time.

In a sense, though, perhaps the decision has already been made for us. With the era of lifetime employment long past and companies discharging employees at a faster rate than ever before, it may be time to recognize that we are all freelancers now.

The post Twenty Years as a Freelance Web Developer: Wisdom Gained and Lessons Learned appeared first on CSS-Tricks.

What makes a good front-end developer?

Css Tricks - Mon, 09/17/2018 - 9:54am

Defining what a front-end developer is and what they do is tough as it is. So, how do we set the bar for what makes for a good front-end developer?

Here's what a few folks have to say on the topic.

I’ll argue that front-end developers need to master four different skills.

  1. Empathy
  2. Code
  3. Design
  4. Communication
Zell Liew

Front-End Developers, having learnt HTML, CSS and JS, are forced to take functionality into account when creating user experiences or making sure that the two disciplines work as one from a development perspective. They become all-rounders, having to understand what is actually happening between the AJAX data and the PHP file that’s sending off a mail or returning errors.

Daine Mawer

In my opinion, what defines a good front-end developer is one that has skilled knowledge of HTML, CSS, JS with a vast understanding of User design thinking as they'll be building web interfaces with accessibility in mind. They should also be excited to learn, as the world of Front-End Development keeps evolving. The ability to stay in the loop is critical.

Egwuenu Gift

After I started to feel more comfortable with my responsibilities ... I soon found my next challenge: to help build a stronger connection between the design and development teams. Though we regularly collaborated to produce high-quality work, these teams didn’t always speak the same language.

Ronald Méndez

I think that front-end developers need to have a holistic view of the architecture of the software that they and their team are creating. They can't silo themselves on the Front-End, but need to have an appreciation for the complexities of the Back-End as well in order to create the best user experience for their customers. In the end, it's about continual learning and team communication, as well as listening to the customer to create a great experience.

Jen Looper

The longer I work on the web, the more I realize that what separates the good people from the really good people isn’t what they know; it’s how they think. Obviously knowledge is important—critical in some cases—but in a field that changes so quickly, how you go about acquiring that knowledge is always going to be more important (at least in the long term) than what you know at any given time. And perhaps most important of all: how you use that knowledge to solve everyday problems.

Philip Walton

Having a working understanding of HTML, CSS and JS is certainly a no-brainer, but it's only one part of the equation. I believe a good front-ender connects the dots between user experiences and business goals while closing any gaps that would prevent holistic user flows. That requires good communication, creative problem solving, empathy and, perhaps above all, an willingness to listen to and accept criticism.

Geoff Graham

It's a difficult question in some ways because the nature of Front-end Development is constantly expanding. The types of things we build as front ends become increasingly complex and varied.

For that reason, I think a good Front-end Developer understands the scope, requirements, and technical restraints of the project they are currently working on. This can invariably mean: what their teams expect from them, what their users need, and because things are changing- curiosity!

Sarah Drasner

I admire how good front-end developers answer questions. If they’re super dogmatic about this one particular approach to something being the only one true way then I start to worry. Take SVG illustrations. Or image optimization. Or how to markup navigation. There’s a lot of different ways to tackle each of those things and none of them are perfect. On this note, Chris wrote a wonderful post all about dogmatism a while back and I think about it all the time. That’s the mark of a great front-end developer right there: someone who’s okay with not having the perfect answers all the time.

Robin Rendle

A good front-end developer is flexible, eager to learn, eager to share and has a pragmatic approach to the ever-changing landscape

Oh yeah, and something something cascade.

Andy Bell What do you think?

This is an open conversation. No right answers. No wrong answers. How would you grade a "good" front-end developer?

The post What makes a good front-end developer? appeared first on CSS-Tricks.

Aspect Ratio Media Elements and intrinsicsize

Css Tricks - Mon, 09/17/2018 - 3:50am

If you need an aspect-ratio sized <div> (or any element that can have children), you can do it. Perhaps the cleanest way is a custom-property-sized pseudo-element that pushes the correct minimum height through padding-based-on-width.

But media elements like <img> don't have children. The <video> tag isn't self-closing, but when it is supported (almost always), the content of it is replaced with a shadow DOM you don't control. Besides, these are the only two elements that "size to an external resource." So, how do you enforce aspect ratio on them when using a variable width like 100% or 75vw? Well, once they load, they will have their natural aspect ratio, so that's nice. But it also means they don't know the height while they are loading and it may cause performance jank-ening reflow.

One solution is to put them into a container with an aspect ratio, forcing them to the corners with absolute positioning. But, all by themselves, they are incapable of sizing to the aspect ratio correctly until they load.

Hence, the intrinsicsize attribute for "all image element types (including SVG images) and videos" that is now under development.

<img intrinsicsize="400x300" style="width: 100%">

The explainer document is helpful. The reason it is intrinsicsize and not aspectratio is because an aspect ratio doesn't provide as much useful or usable information. I'd love to see it work on any element and be brought to CSS as well.

The post Aspect Ratio Media Elements and intrinsicsize appeared first on CSS-Tricks.

Removing jQuery from frontend

Css Tricks - Fri, 09/14/2018 - 12:00pm

Here’s how and why the team at GitHub has slowly been deprecating jQuery from their codebase:

We have recently completed a milestone where we were able to drop jQuery as a dependency of the frontend code for This marks the end of a gradual, years-long transition of increasingly decoupling from jQuery until we were able to completely remove the library. In this post, we will explain a bit of history of how we started depending on jQuery in the first place, how we realized when it was no longer needed, and point out that—instead of replacing it with another library or framework—we were able to achieve everything that we needed using standard browser APIs.

The team explores how using tools like eslint-plugin-jquery discourages developers at GitHub from using jQuery, but the team also notes that they decided to remove certain design behaviors altogether to help them achieve this goal:

As part of our refined approach to building frontend features on, we focused on getting away with regular HTML foundation as much as we could, and only adding JavaScript behaviors as progressive enhancement. As a result, even those web forms and other UI elements that were enhanced using JS would usually also work with JavaScript disabled in the browser. In some cases, we were able to delete certain legacy behaviors altogether instead of having to rewrite them in vanilla JS.

I think all of this is wonderful news. It’s good for jQuery, it’s good for developers, and it’s good for the web. But it also shows just how far browsers have come since the first release of jQuery back in 2006. What will browsers be capable of 12 years from now, I wonder.

Direct Link to ArticlePermalink

The post Removing jQuery from frontend appeared first on CSS-Tricks.

Syndicate content
©2003 - Present Akamai Design & Development.