Front End Web Development

Using npm as a Build Tool

Css Tricks - Sat, 04/29/2017 - 2:32am

The main purpose being: you're using npm anyway, so using it directly to run scripts removes a dependency (i.e. gulp/grunt/whatever) and brings you a bit closer to the tools you are using directly. I could see this example `package.json` file from Graham Smith being highly referenced as people try this out for themselves.

Remember Damon Bauer covered this here on CSS-Tricks last year, with a whole bunch of examples of what is possible.

Direct Link to ArticlePermalink

Using npm as a Build Tool is a post from CSS-Tricks

TypeScript at Slack

Css Tricks - Sat, 04/29/2017 - 2:25am

An excellent subhead by Felix Rieseberg: How I Learned to Stop Worrying & Trust the Compiler.

I'd wager that some of the popularity of SCSS was due to that fact that any valid CSS was valid SCSS, so you could baby step into SCSS on an existing codebase fairly easily. The same is true with TypeScript:

Modern JavaScript is valid TypeScript, meaning that one can use TypeScript without changing a single line of code. This allowed us to use "gradual typing" by enabling the compiler and the static analysis early, without suspending work on critical bug fixes or new features.

And, also like SCSS, you get immediate benefit from the baby stepping. You'll find bugs right away:

... the more lines of code a human writes, the more inevitable it becomes to misspell a property, assume the parent of a nested object to always exist, or to use a non-standard error object.

What appeals to me the most though, is what TypeScript does to your IDE:

TypeScript understands which properties and methods are available on certain objects, enabling your editor to do the same. An autocomplete system that only uses words in the current document feels barbaric afterward.

Direct Link to ArticlePermalink

TypeScript at Slack is a post from CSS-Tricks

Managing State in CSS with Reusable JavaScript Functions

Css Tricks - Fri, 04/28/2017 - 2:50am

Determining the most efficient way of managing state can be a challenging issue in CSS, but thankfully there are many OOCSS-based methodologies out there which provide some good solutions. My preferred comes from SMACSS (Scalable and modular architecture for CSS) and involves stateful classes. To quote SMACSS's own documentation, stateful classes are:

A state is something that augments and overrides all other styles. For example, an accordion section may be in a collapsed or expanded state. A message may be in a success or error state.

States are generally applied to the same element as a layout rule or applied to the same element as a base module class.

One of my most-used stateful classes is is-active. Taking the accordion example from the prior quote, is-active in this instance would apply all the required CSS styles to represent an expanded state. As seen in the example below:

See the Pen #1) Accordion Component w Stateful Class by Luke Harrison (@lukedidit) on CodePen.

You will notice there's some JavaScript which toggles the is-active class on the component when a click event is detected:

var accordion = document.querySelectorAll(".c-accordion"); for(var i = 0; i < accordion.length; i++) { var accordionHeader = accordion[i].querySelector(".c-accordion__header"), accordionCurrent = accordion[i]; accordionHeader.addEventListener("click", function(){ accordionCurrent.classList.toggle("is-active"); }); }

Whilst valid JavaScript, this would have to be repeated again and again for any other components which leverage the is-active stateful class via a click event, leading to many duplicates of what is essentially the same code snippet.

Not very efficient and certainly not very DRY.

A better approach would be instead to write a single function which performs the same task and can be reused over and over again with different components. Let's do that.

Creating a simple reusable function

Let's start off by building a simple function which accepts an element as a parameter and toggles is-active:

var makeActive = function(elem){ elem.classList.toggle("is-active"); }

This works fine, but if we slot it into our accordion JavaScript there's a problem:

var accordion = document.querySelectorAll(".c-accordion"), makeActive = function(elem){ elem.classList.toggle("is-active"); } for(var i = 0; i < accordion.length; i++) { var accordionHeader = accordion[i].querySelector(".c-accordion__header"), accordionCurrent = accordion[i]; accordionHeader.addEventListener("click", function(){ makeActive(accordionCurrent); }); }

Although the makeActive function is reusable, we still need to first write code to grab our component and any of its inner elements, so there's certainly lots of room for improvement.

To make these improvements, we can leverage HTML5 custom data attributes:

<div class="c-accordion js-accordion"> <div class="c-accordion__header" data-active="js-accordion">My Accordion Component</div> <div class="c-accordion__content-wrapper"> <div class="c-accordion__content"> Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce laoreet ultricies risus, sit amet congue nulla mollis et. Suspendisse bibendum eros sed sem facilisis ornare. Donec sit amet erat vel dui semper pretium facilisis eget nisi. Fusce consectetur vehicula libero vitae faucibus. Nullam sed orci leo. Fusce dapibus est velit, at maximus turpis iaculis in. Pellentesque ultricies ultrices nisl, eu consequat est molestie sit amet. Phasellus laoreet magna felis, ut vulputate justo tempor eu. Nam commodo aliquam vulputate. </div> </div> </div>

A data-active attribute has been added to the element which previously triggered the is-active toggle when clicked. This attribute's value represents the element where the is-active toggle should take place, which as before is the top-level c-accordion element. Note the addition of a new js-accordion class rather than hooking into the existing c-accordion class. This is to decouple functional aspects of the component from it's styling.

Let's take a look at the JavaScript:

// Grab all elements with data-active attribute var elems = document.querySelectorAll("[data-active]"); // Loop through if any are found for(var i = 0; i < elems.length; i++){ // Add event listeners to each one elems[i].addEventListener("click", function(e){ // Prevent default action of element e.preventDefault(); // Grab linked elements var linkedElement = document.querySelectorAll("." + this.getAttribute("data-active")); // Toggle linked element if present for(var i = 0; i < linkedElement.length; i++) { linkedElement[i].classList.toggle("is-active"); } }); }

This has certainly improved things as we no longer have to write code to grab any elements, just attach a data-active attribute to our trigger element and specify a target element. As it stands, this function can be used for any other component where a click-based is-active class is required without any additional coding. Full example below:

See the Pen #2) Accordion Component w reusable is-active function by Luke Harrison (@lukedidit) on CodePen.

Improving our reusable function

This reusable function works, but when scaled, we have to take care to make sure trigger and target element classes don't conflict with one another. In the example below, clicking one accordion would trigger is-active on all of them.

<div class="c-accordion js-accordion"> <div class="c-accordion__header" data-active="js-accordion">First Accordion</div> [...] </div> <div class="c-accordion js-accordion"> <div class="c-accordion__header" data-active="js-accordion">Second Accordion</div> [...] </div> <div class="c-accordion js-accordion"> <div class="c-accordion__header" data-active="js-accordion">Third Accordion</div> [...] </div>

Adding number suffixes to each js-accordion reference does solve the problem, but it's a hassle which we can do without. A good solution would be to instead implement scoping to our reusable function which would enable us to encapsulate our toggles so they only effect the elements we want.

To implement scoping, we'll need to create a separate custom attribute called data-active-scope. Its value should represent the parent element which the toggle should be encapsulated within, which in this instance is the parent js-accordion element.

<div class="c-accordion js-accordion"> <div class="c-accordion__header" data-active="js-accordion" data-active-scope="js-accordion">First Accordion</div> [...] </div> <div class="c-accordion js-accordion"> <div class="c-accordion__header" data-active="js-accordion">Second Accordion</div> [...] </div>

Using the above HTML, the following behaviour should happen:

  1. When you click the first accordion, because it has a scope set to js-accordion, only data-active elements which match or are children of this js-accordion instance will have is-active toggled.
  2. When you click the second accordion, which doesn't have a scope, is-active would be toggled on all instances of js-accordion.

Provided data-active-scope is correctly set, any class toggles within each js-accordion element should be encapsulated regardless of any conflicting classnames.

Here's the modified Javascript and a working example showing accordions with and without a data-active-scope attribute:

// Grab all elements with data-active attribute var elems = document.querySelectorAll("[data-active]"), // closestParent helper function closestParent = function(child, match) { if (!child || child == document) { return null; } if (child.classList.contains(match) || child.nodeName.toLowerCase() == match) { return child; } else { return closestParent(child.parentNode, match); } } // Loop through if any are found for(var i = 0; i < elems.length; i++){ // Add event listeners to each one elems[i].addEventListener("click", function(e){ // Prevent default action of element e.preventDefault(); // Grab scope if defined if(this.getAttribute("data-active-scope")) { var scopeElement = closestParent(this, this.getAttribute("data-active-scope")); } if(scopeElement) { // Grab scoped linked element var linkedElement = scopeElement.querySelectorAll("." + this.getAttribute("data-active")); // Convert to array linkedElement = Array.prototype.slice.call(linkedElement); // Check if our scope matches our target element and add to array if true. // This is to make sure everything works when data-active matches data-active-scope. if(scopeElement.classList.contains(this.getAttribute("data-active"))) { linkedElement.unshift(scopeElement); } } else { // Grab linked element var linkedElement = document.querySelectorAll("." + this.getAttribute("data-active")); } // Toggle linked element if present for(var i = 0; i < linkedElement.length; i++) { linkedElement[i].classList.toggle("is-active"); } }); }

See the Pen #3) Accordion Component w Improved reusable is-active function by Luke Harrison (@lukedidit) on CodePen.

Moving beyond is-active

Our reusable function is now working nicely and is an efficient way of setting up is-active toggles on all kinds of components. However what if we need to set up a similar toggle for another stateful class? As it stands we would have to duplicate the function and change all references of is-active to the new stateful class. Not very efficient.

We should improve our reusable function to accept any class by refactoring our data-attributes. Instead of attaching the data-active attribute to our trigger element, let's replace it with the following:

  • data-class - The class we wish to add.
  • data-class-element - The element we wish to add the class to.
  • data-class-scope - The scope attribute performs the same function, but has been renamed for consistency.

This requires a few minor tweaks to our JavaScript:

// Grab all elements with data-active attribute var elems = document.querySelectorAll("[data-class][data-class-element]"); // closestParent helper function closestParent = function(child, match) { if (!child || child == document) { return null; } if (child.classList.contains(match) || child.nodeName.toLowerCase() == match) { return child; } else { return closestParent(child.parentNode, match); } } // Loop through if any are found for(var i = 0; i < elems.length; i++){ // Add event listeners to each one elems[i].addEventListener("click", function(e){ // Prevent default action of element e.preventDefault(); // Grab scope if defined if(this.getAttribute("data-class-scope")) { var scopeElement = closestParent(this, this.getAttribute("data-class-scope")); } if(scopeElement) { // Grab scoped linked element var linkedElement = scopeElement.querySelectorAll("." + this.getAttribute("data-class-element")); // Convert to array linkedElement = Array.prototype.slice.call(linkedElement); // Check if our scope matches our target element and add to array if true. // This is to make sure everything works when data-active matches data-active-scope. if(scopeElement.classList.contains(this.getAttribute("data-class-element"))) { linkedElement.unshift(scopeElement); } } else { // Grab linked element var linkedElement = document.querySelectorAll("." + this.getAttribute("data-class-element")); } // Toggle linked element if present for(var i = 0; i < linkedElement.length; i++) { linkedElement[i].classList.toggle(this.getAttribute("data-class")); } }); }

It would be set up in the HTML like so:

<button class="c-button" data-class="is-loading" data-class-element="js-form-area">Submit</button>

In the example below, clicking the c-button component toggles the is-loading class on the js-form-area component:

See the Pen #4) Form Component w Improved reusable any class function by Luke Harrison (@lukedidit) on CodePen.

Handling multiple toggles

So we have a reusable function which toggles any class on any element. These click events can be set up without having to write any additional JavaScript through the use of custom data attributes. However, there's still ways to make this reusable function even more useful.

Coming back to our previous example of the login form component, what if when the c-button element is clicked, in addition to it toggling is-loading on js-form-area, we also want to toggle is-disabled on all instances of c-input? At the moment this isn't possible as our custom attributes only accept a single value each.

Let's modify our function, so instead of each custom data attribute only accepting a single value, it accepts a comma separated list of values - with each item value in data-class linking with the value of a matching index in data-class-element and data-class-scope.

Like so:

<button class="c-button" data-class="is-loading, is-disabled" data-class-element="js-form-area, js-input" data-class-scope="false, js-form-area">Submit</button>

Assuming the above is used, the following would happen once c-button is clicked:

  1. is-loading would be toggled on js-form-area.
  2. is-disabled would be toggled on js-input and be scoped within the parent js-form-area element.

This requires more changes to our JavaScript:

// Grab all elements with data-active attribute var elems = document.querySelectorAll("[data-class][data-class-element]"); // closestParent helper function closestParent = function(child, match) { if (!child || child == document) { return null; } if (child.classList.contains(match) || child.nodeName.toLowerCase() == match) { return child; } else { return closestParent(child.parentNode, match); } } // Loop through if any are found for(var i = 0; i < elems.length; i++){ // Add event listeners to each one elems[i].addEventListener("click", function(e){ // Prevent default action of element e.preventDefault(); // Grab classes list and convert to array var dataClass = this.getAttribute('data-class'); dataClass = dataClass.split(", "); // Grab linked elements list and convert to array var dataClassElement = this.getAttribute('data-class-element'); dataClassElement = dataClassElement.split(", "); // Grab data-scope list if present and convert to array if(this.getAttribute("data-class-scope")) { var dataClassScope = this.getAttribute("data-class-scope"); dataClassScope = dataClassScope.split(", "); } // Loop through all our dataClassElement items for(var b = 0; b < dataClassElement.length; b++) { // Grab elem references, apply scope if found if(dataClassScope && dataClassScope[b] !== "false") { // Grab parent var elemParent = closestParent(this, dataClassScope[b]), // Grab all matching child elements of parent elemRef = elemParent.querySelectorAll("." + dataClassElement[b]); // Convert to array elemRef = Array.prototype.slice.call(elemRef); // Add parent if it matches the data-class-element and fits within scope if(dataClassScope[b] === dataClassElement[b] && elemParent.classList.contains(dataClassElement[b])) { elemRef.unshift(elemParent); } } else { var elemRef = document.querySelectorAll("." + dataClassElement[b]); } // Grab class we will add var elemClass = dataClass[b]; // Do for(var c = 0; c < elemRef.length; c++) { elemRef[c].classList.toggle(elemClass); } } }); }

And here's another working example:

See the Pen #5) Form Component w Improved reusable + multiple any class function by Luke Harrison (@lukedidit) on CodePen.

Moving beyond toggle

Our reusable function is quite useful now, but it makes a presumption that toggling classes is the desired behavior. What if when clicked we want the trigger to remove a class if it's present and do nothing otherwise? Currently, that's not possible.

To round the function off let's integrate a bit of extra logic to allow for this behaviour. We'll introduce an optional data-attribute called data-class-behaviour which accepts the following options:

  • toggle - Toggles data-class on data-class-element. This should also be the default behaviour which happens if data-class-behaviour isn't defined.
  • add - Adds data-class on data-class-element if it isn't already present. If it is, nothing happens.
  • remove - Removes data-class on data-class-element if it's already present. If it isn't, nothing happens.

As with previous data attributes, this new optional attribute will be a comma-separated list to allow for different behaviours for each action. Like so:

<button class="c-button" data-class="is-loading, is-disabled" data-class-element="js-form-area, js-input" data-class-behaviour="toggle, remove">Submit</button>

Assuming the above HTML is used, the following would happen once c-button is clicked:

  1. is-loading would be toggled on js-form-area
  2. is-disabled would be removed from js-input if present.

Let's make the necessary JavaScript changes:

// Grab all elements with data-active attribute var elems = document.querySelectorAll("[data-class][data-class-element]"); // closestParent helper function closestParent = function(child, match) { if (!child || child == document) { return null; } if (child.classList.contains(match) || child.nodeName.toLowerCase() == match) { return child; } else { return closestParent(child.parentNode, match); } } // Loop through if any are found for(var i = 0; i < elems.length; i++){ // Add event listeners to each one elems[i].addEventListener("click", function(e){ // Prevent default action of element e.preventDefault(); // Grab classes list and convert to array var dataClass = this.getAttribute('data-class'); dataClass = dataClass.split(", "); // Grab linked elements list and convert to array var dataClassElement = this.getAttribute('data-class-element'); dataClassElement = dataClassElement.split(", "); // Grab data-class-behaviour list if present and convert to array if(this.getAttribute("data-class-behaviour")) { var dataClassBehaviour = this.getAttribute("data-class-behaviour"); dataClassBehaviour = dataClassBehaviour.split(", "); } // Grab data-scope list if present and convert to array if(this.getAttribute("data-class-scope")) { var dataClassScope = this.getAttribute("data-class-scope"); dataClassScope = dataClassScope.split(", "); } // Loop through all our dataClassElement items for(var b = 0; b < dataClassElement.length; b++) { // Grab elem references, apply scope if found if(dataClassScope && dataClassScope[b] !== "false") { // Grab parent var elemParent = closestParent(this, dataClassScope[b]), // Grab all matching child elements of parent elemRef = elemParent.querySelectorAll("." + dataClassElement[b]); // Convert to array elemRef = Array.prototype.slice.call(elemRef); // Add parent if it matches the data-class-element and fits within scope if(dataClassScope[b] === dataClassElement[b] && elemParent.classList.contains(dataClassElement[b])) { elemRef.unshift(elemParent); } } else { var elemRef = document.querySelectorAll("." + dataClassElement[b]); } // Grab class we will add var elemClass = dataClass[b]; // Grab behaviour if any exists if(dataClassBehaviour) { var elemBehaviour = dataClassBehaviour[b]; } // Do for(var c = 0; c < elemRef.length; c++) { if(elemBehaviour === "add") { if(!elemRef[c].classList.contains(elemClass)) { elemRef[c].classList.add(elemClass); } } else if(elemBehaviour === "remove") { if(elemRef[c].classList.contains(elemClass)) { elemRef[c].classList.remove(elemClass); } } else { elemRef[c].classList.toggle(elemClass); } } } }); }

And finally, a working example:

See the Pen #6) Form Component w Improved reusable + multiple any class + behaviours function by Luke Harrison (@lukedidit) on CodePen.

Closing

What we've created is a powerful function which can be reused over and over again without writing any extra code. It allows us to quickly assign add, remove or toggle logic for multiple stateful classes on click and lets us scope these changes to the desired area.

There's still many ways in which this reusable function can be improved even further:

  • Support for using different events other than click.
  • Swipe support for touch devices.
  • Some form of simple validation which allows you to declare JavaScript variables which must be truthy before a class change goes ahead.

In the meantime, if you have any ideas for your own improvements or even a completely different method of managing stateful classes altogether, then be sure to let me know in the comments below.

Managing State in CSS with Reusable JavaScript Functions is a post from CSS-Tricks

Poly Fluid Sizing

Css Tricks - Thu, 04/27/2017 - 12:58pm

Fluid typography is pretty amazing. We have a writeup of how it all works. But as fancy as that is, it's still scaling the type linearly. What if we wanted the type size to fall along a curve? The math gets a bunch more complicated, but it's possible.

Jake Wilson digs in, and while he finds that calc() isn't quite up for the job (e.g. font-size: calc(3vw * 3vw); /* This doesn't work in CSS */), he does land on a technique he's calling Poly Fluid Sizing, which takes a map of breakpoints and font sizes and linear interpolates them just about as good (*it depends*).

Direct Link to ArticlePermalink

Poly Fluid Sizing is a post from CSS-Tricks

Beautiful, Customizable Online Appointment Scheduling

Css Tricks - Thu, 04/27/2017 - 3:09am

Brand new designs for Acuity Scheduling are beautiful out of the box and make it easy to provide online appointment scheduling for you or your clients, matching their identity. The online scheduler comes with several templates, embeds quickly in existing websites, and is fully customizable with advanced CSS.

Advanced CSS Customization

Customize nearly everything on your scheduler with our simple built-in options, or bring your creative ideas to life with our advanced CSS editor. Custom fonts can be imported, and standard CSS selectors let you change the appearance of almost anything:

Embedding a Client Scheduler

Two lines of HTML — an iframe, and an optional helper script — add the appointment scheduling widget to your website. The embedded scheduler has a number of unique designs including daily and monthly views, a class schedule, and a lightbox booking button. Create unique links to streamline the booking process for clients by pre-filling their info, or simplify workflows and create a single-click booking experience.

Customize your online scheduling experience today — Try Acuity Scheduling for free!

Direct Link to ArticlePermalink

Beautiful, Customizable Online Appointment Scheduling is a post from CSS-Tricks

The Different Logical Ways to Group CSS Properties

Css Tricks - Thu, 04/27/2017 - 2:49am

Over on the MediaTemple Blog, I talk about some logical possibilities for how you might arrange the declarations within a ruleset. Personally:

I'll admit, I traditionally haven't had much of an opinion about the ordering of CSS properties. I just add what I need. I think they end up largely "grouped" by related things because that's just how my brain spits them out.

While writing this, I looked into CSS Comb again, and I'm starting to be convinced this is a good idea. I don't know if it's worth the tedious work of manually organizing properties, but I can see the advantages of code that is meticulously organized, so having a computer do it seems like a good idea.

Direct Link to ArticlePermalink

The Different Logical Ways to Group CSS Properties is a post from CSS-Tricks

Which Projects Need React? All Of Them!

Css Tricks - Wed, 04/26/2017 - 2:47am

When does a project need React? That's the question Chris Coyier addressed in a recent blog post. I'm a big fan of Chris' writing, so I was curious to see what he had to say.

In a nutshell, Chris puts forward a series of good and bad reasons why one might want to use React (or other similar modern JavaScript libraries) on a project. Yet while I don't disagree with his arguments, I still find myself coming to a different conclusion.

So today, I'm here to argue that the answer to "When does a project need React?" is not "it depends". It's "every time".

React vs Vue vs Angular vs…

First, let's get something out of the way: in his article, Chris picked React as a stand-in for "front-end libraries" in general, and I'll do the same here. Plus, React is what I'm most familiar with from my ongoing work on VulcanJS, a React and GraphQL framework.

That being said, my arguments should apply equally well to any other library that offers the same features as React.

The Power of the Hammer

When all you have is a hammer, everything looks like a nail.

This proverb has long been used to condemn anybody trying to apply a systematic one-size-fits-all approach to every problem.

But let's suppose for a moment that you did live in a world full of nails (however uncomfortable this might sound), and that your trusty hammer was able to take care of any issues you encounter.

Just consider the benefits of being able to reuse the same tool every time:

  • No time spent on deciding which tool to use.
  • Less time spent having to learn new tools.
  • More time to get better at wielding your tool of choice.

So is React that tool? I think it just might be!

The Complexity Spectrum

First, let's address the most common argument against the "React all the things!" approach. I'll quote directly from Chris:

A blog, for example, probably has none of the problems and fits none of the scenarios that would make React a good fit. And because it's not a good fit, it's probably a bad fit, because it introduces complicated technology and dependencies for something that doesn't call for it.

Fair enough. A simple blog doesn't need React. After all, even if you need a bit of JavaScript to hook up a newsletter sign-up form, you can just use jQuery.

What's that? You need to use that form in multiple places on different pages? And only show it under certain conditions? And animate it, too? Wait, hold on…

The point I'm trying to make with this little scenario is that complexity is not an all-or-nothing, binary choice. Instead, modern websites live on a continuous spectrum that goes from static page all the way to rich single-page app.

So maybe your project is comfortably nested at the "simple" end of the spectrum now, but what about six months down the road? Isn't it better to pick a technology that leaves you room to grow, rather than one that pigeon-holes you into bad practices?

The Benefits of React

Premature optimization is the root of all evil.

Another popular saying among programmers. After all, who needs a hammer and nails when duct tape will do just fine!

But this makes the assumption that "premature optimization" is a long, arduous process with few benefits. And I don't think this applies to React.

While React may take some time getting used to, once you learn its basic concepts you'll be just as productive as with classic front-end tools.

Maybe more in fact, because React leverages the extremely powerful concept of components. Just like CSS encourages you to think in terms of reusable classes and styles, React pushes you towards a flexible, modular front-end architecture that has benefits for every use case, from the lowly static homepage to the interactive back-end dashboard.

JavaScript, JavaScript Everywhere

We live in a JavaScript world. Or, as Chris puts it:

You got Node.js on the server side. There are loads of projects that yank CSS out of the mix and handle styles through JavaScript. And with React, your HTML is in JavaScript too.

All JavaScript! All hail JavaScript!

Chris isn't quite convinced, but I am. JavaScript in itself isn't necessarily perfect, but having access to the entire modern NPM ecosystem is amazing.

Installing a jQuery plugin used to involve finding its homepage, downloading it, copying it in your project directory, adding a <script> tag, and then hopefully remembering to check back every couple months for new versions. These days, installing the same plugin as a React package is just the matter of a single npm install command.

And with new libraries like styled-components, even CSS is now being dragged kicking and screaming into the future.

Believe me, once you get used to this world where everything is speaking the same language, it's really hard to go back to the old way of doing things.

Won't Somebody Please Think of the Users!

I know what you're thinking: so far I've tried to sell you on the benefits of React to developers, but I've carefully side-stepped any mention of the end user experience.

And that remains the key argument against modern libraries: slow, JavaScript-bloated sites that take ages just to display a single "one weird trick" ad.

Except here's a little secret: you can get all the benefits of React without any JavaScript at all!

What I'm talking about here is rendering React on the server. In fact, tools like Gatsby (and soon, Next.js) even let you compile React components into static HTML files that you can host on, say, GitHub pages.

As an example, my own personal site is a Gatsby-generated React app that doesn't load any JavaScript at all (beyond a Google Analytics snippet). I get all the benefits of using React in development (all-JavaScript, access to the NPM ecosystem, styled-components, etc.) but end up with a 100% HTML-and-CSS end product.

Wrapping Up

To recap, here are the four reasons why I think React is a valid choice for any project:

  • It's really hard to guarantee you'll never ever need interactive features like tabs, forms, etc. even for the simplest of site.
  • React's component-based approach has big benefits even for static content-based sites.
  • Access to the modern JavaScript ecosystem is a huge benefit.
  • Modern server-rendering tools eliminate the downsides of using React for the end user.

So what do you think, Chris? Have I made a convincing case? Or do doubts still linger in your mind?

And what about you, dear reader? Whether you think like Chris that every tool has its use, or whether you agree with me that the Time of the Hammer is at hand, let us know in the comments!

Which Projects Need React? All Of Them! is a post from CSS-Tricks

React Sketch.app

Css Tricks - Wed, 04/26/2017 - 2:35am

The "normal" workflow I'm sure we've all lived is that design happens, then coding happens. A healthy workflow has back-and-forth between everyone involved in a project, including designers and developers, but still: The code is the final product. You design your way to code, you don't code your way to designs.

It was only a little over a month ago when it was news that Sketch 43 was moving to a .JSON file format. The final release notes drop the news quite blasé:

Revised file format

But Jasim A Basheer rightly made a big deal of it:

... it will fundamentally change how the design tools game will be played out in the coming years.

"enables more powerful integrations for third-party developers" is stating it lightly. This is what the fine folks at Bohemian Coding has done?—?they opened up Sketch's file format into a neat JSON making it possible for anyone to create and modify Sketch compatible files.

"Interesting." I thought to myself. "It's like an API to a design document. I wonder how this will play out." Little did I know just weeks later we'd see a really powerful tool drop.

Jon Gold, for Airbnb:

... share a tool we built to help bridge the gap between designers and engineers working on design systems at scale. React-sketchapp is an open-source library that allows you to write React components that render to Sketch documents.

It's worth embedding one of their videos here:

Coding your way to design documents! Which makes more and more sense, as design tooling and code tools converge on concepts:

In Sketch, we use symbols and overrides, in React we use components and properties. The concepts are so similar that it seemed silly not to unify them.

Emphasis Jon's.

We also wanted to minimize sources of truth. Why keep a separate library of components drawn by hand in Sketch once we have them implemented as the real thing used every day by millions of people?

The fewer sources of truth we have for a design system, the more efficient we are.

Direct Link to ArticlePermalink

React Sketch.app is a post from CSS-Tricks

New fonts on Typekit from Lettersoup

Nice Web Type - Tue, 04/25/2017 - 5:48am

We’re delighted to add several new fonts to our library from Berlin-based type foundry Lettersoup, founded by Botio Nikoltchev in 2014. If you already have an account with us, or a paid Creative Cloud subscription, these fonts are all part of your collection and can be used on the web or synced. Check them out and let us know what you think!

Milka

Bulgarian artist Milka Peikova designed the stencil alphabet that would become Milka in 1979, which Lettersoup has now turned into a fully-supported digital font. Milka passed away in 2016 at the age of 96, but worked with Botio on the revival design beginning in 2014 along with Ani Petrova and Anelia Pashova — and, back in Berlin, with Adam Twardoch and Andreas Eigendorf. The echo of the late 1970s is strong here, but the design doesn’t feel remotely dated. The six different styles are a fascinating exploration of the effect a slight texture can have on the overall mood.

Quasimoda

Speaking of moods! Quasimoda comes in eleven weights, giving you ample variety when designing around any number of constraints. The extreme weights make for excellent headers or subheads, and at medium weights the type is beautifully proportioned for a smooth reading experience with longer texts. Friendly geometric shapes are a feature at all weights, and the relatively small x-height and long descenders makes this a great typeface to pair with Garamonds or similar serifs.

Ropa Sans, Soft, & Mix

Ropa Sans

The influence of DIN — classic rectangular precision — is definitely visible in Ropa Sans, Soft, and Mix. Botio refers to the three subfamilies as siblings of one another, with Ropa Sans the most straightforward and technically-minded of the trio. It’s certainly the most DIN-like.

Ropa Soft

Ropa Soft introduces a warmer personality, especially noticeable at the thicker weights. The italics are a lovely and striking feature in all the different subfamilies, perhaps most prominently in Ropa Mix where those narrow lines make an emphatic contrast within the letterforms.

Ropa Mix

Let us know what you think — will you mix together a couple different Ropa styles, or maybe experiment a little with Milka? We’d love to know what you’re working on. Tag us (and the fonts!) anytime on Instagram. We love seeing fonts in use!


Now that CSS Custom Properties are a Thing, All Value Parts Can Be Changed Individually

Css Tricks - Tue, 04/25/2017 - 5:21am

In CSS, some properties have shorthand. One property that takes separated values. Syntactic sugar, as they say, to make authoring easier. Take transition, which might look something like:

.element { transition: border 0.2s ease-in-out; }

We could have written it like this:

.element { transition-property: border; transition-duration: 0.2s; transition-timing-function: ease-in-out; }

Every "part" of the shorthand value has its own property it maps to. But that's not true for everything. Take box-shadow:

.element { box-shadow: 0 0 10px #333; }

That's not shorthand for other properties. There is no box-shadow-color or box-shadow-offset.

That's where Custom Properties come to save us!

We could set it up like this:

:root { --box-shadow-offset-x: 10px; --box-shadow-offset-y: 2px; --box-shadow-blur: 5px; --box-shadow-spread: 0; --box-shadow-color: #333; } .element { box-shadow: var(--box-shadow-offset-x) var(--box-shadow-offset-y) var(--box-shadow-blur) var(--box-shadow-spread) var(--box-shadow-color); }

A bit verbose, perhaps, but gets the job done.

Now that we've done that, remember we get some uniquely cool things:

  1. We can change individual values with JavaScript. Like:

    document.documentElement.style.setProperty("--box-shadow-color", "green");
  2. Use the cascade, if we need to. If we set --box-shadow-color: blue on any selector more specific than the :root, we'll override that color.

Fallbacks are possible too, in case the variable isn't set at all:

.element { box-shadow: var(--box-shadow-offset-x, 0) var(--box-shadow-offset-y, 0) var(--box-shadow-blur, 5px) var(--box-shadow-spread, 0) var(--box-shadow-color, black); }

How about transforms? They are fun because they take a space-separated list of values, so each of them could be a custom property:

:root { --transform_1: scale(2); --transform_2: rotate(10deg); } .element{ transform: var(--transform_1) var(--transform_2); }

What about elements that do have individual properties for their shorthand, but also offer comma-separated multiple values? Another great use-case:

:root { --bgImage: url(basic_map.svg); --image_1_position: 50px 20px; --image_2_position: bottom right; } .element { background: var(--bgImage) no-repeat var(--image_1_position), var(--bgImage) no-repeat var(--image_2_position); }

Or transitions?

:root { --transition_1_property: border; --transition_1_duration: 0.2s; --transition_1_timing_function: ease; --transition_2_property: background; --transition_2_duration: 1s; --transition_2_timing_function: ease-in-out; } .element { transition: var(--transition_1_property) var(--transition_1_duration) var(--transition_1_timing_function), var(--transition_2_property) var(--transition_2_duration) var(--transition_2_timing_function), }

Dan Wilson recently used this kind of thing with animations to show how it's possible to pause individual animations!

Here's browser support:

Green indicates full support at the version listed (and above). Yellow indicates partial support. Red indicates no support. See Caniuse for full browser support details.

DesktopChromeOperaFirefoxIEEdgeSafari493631No159.1Mobile / TabletiOS SafariOpera MobileOpera MiniAndroidAndroid ChromeAndroid Firefox9.337No565752

Now that CSS Custom Properties are a Thing, All Value Parts Can Be Changed Individually is a post from CSS-Tricks

PWA Directory

Css Tricks - Tue, 04/25/2017 - 1:18am

The other day I was watching an interview with Ade Oshineye where he discussed his work on the PWA Directory at Google, a showcase of progressive web apps. And it’s pretty neat!

It lists a whole bunch of PWAs out there and you can filter them by Lighthouse metrics – that’s the auditing tool from Google that scores a web app and gives us developers the ability to improve them.

Direct Link to ArticlePermalink

PWA Directory is a post from CSS-Tricks

The Many Tools for Shape Morphing

Css Tricks - Mon, 04/24/2017 - 5:29am

To no one's surprise, I'm sure, there are lots of different ways to do the same thing on the web. Shape morphing, being a thing on the web, is no different. There are some native technologies, some libraries that leverage those, and some libraries that do things all on their own. Let's look at some of the options (with demos) and weigh the advantages and disadvantages.

SMIL

The original, native technology for shape morphing is SMIL. We have both a guide to SMIL on CSS-Tricks, and an article talking about replacements for it, since it doesn't work in Microsoft browsers and Blink threatened to yank it at one point.

I wouldn't suggest doing important work in SMIL but it is OG shape morphing.

See the Pen Sitepoint Challenge #1 in SVG and SMIL by Noah Blon (@noahblon) on CodePen.

Our article How SVG Shape Morphing Works covers SMIL shape morphing in detail, and the demo above is from Noah Blon's An Intro to SVG Animation with SMIL.

To get a feel for the must have same # of points thing, you might enjoy playing with Shape Shifter:

MorphSVG (Greensock GSAP Plugin)

Moving right along to probably the most robust possible option, Greensock's MorphSVG is a powerhouse. Bear in mind:

MorphSVGPlugin is a bonus plugin for Club GreenSock members ("Shockingly Green" and "Business Green" levels). It's our way of showing our gratitude to those who are fueling innovation at GreenSock.

Worth it. Just MorphSVG alone is amazing. Unlike almost any other shape morphing method, it can tween between shapes of any number of points. It does so performantly, in a safe cross-browser fashion, and gives you more fine grain control over how the animation goes down.

See the complex morphing happening here:

See the Pen Morphing SVG Slider - 20th Century Women by Sullivan Nolan (@nolakat) on CodePen.

If you'd like to play with MorphSVG, I created a drag-and-drop Pen to morphing between any two shapes (best results with SVG's with viewBox="0 0 100 100" SVGs with just one <path>):

See the Pen Morph Machine by Chris Coyier (@chriscoyier) on CodePen.

If you're a user of Adobe Muse, you might be interested in the Muse Morph widget which combines Illustrator, Muse, and Greensock MorphSVG.

SnapSVG

SnapSVG's animate() function will animate an SVG element's properties, including path data. Codrops has excellent examples of this in action. Here's a little movie showing some of them off:

SnapSVG is, in a sense, Raphaël's older brother, which could do things like this:

anime.js

The newer anime.js library has shape morphing built in.

CSS

It's a little hard to believe, but CSS is getting in on the shape morphing action! Eric Willigers, a Chrome developer, emailed me last year:

'd' has become a presentation attribute. This allows SVG path elements to be animated using CSS animations and Web Animations, with path('...') keyframes.

I assume this is a spec change, so browsers other than Chrome will, presumably, start allowing this. For now, this works great in Chrome:

See the Pen Simple Path Examples by Chris Coyier (@chriscoyier) on CodePen.

SVG Morpheus

SVG Morpheus is a JavaScript lib entirely devoted to shape morphing. Here's a great demo of it in action:

See the Pen Mobiltelefonens Evolution (SVG Shape Morphing) by Noel Delgado (@noeldelgado) on CodePen.

KUTE.js

There is an SVG plugin for Kute.js that allows for the animation of SVG properties, including shape morphing.

See the Pen Morph SVG with KUTE.js by thednp (@thednp) on CodePen.

The API gives you some control over the morphing, like how precise you want it to be and the ability to reverse the draw direction so different points match up to tween.

d3

d3, probably the biggest library out there for data viz folks, can also do shape morphing. Here's a GIF recording of a demo by Mike Bostock:

There is also a d3 plugin called d3-interpolate-path that helps make it better:

Interpolates path `d` attribute smoothly when A and B have different number of points.

mo.js

"Motion graphics for the web" is the mo.js tagline, another newer library. Oleg Solomka (@LegoMushroom) has some incredible demos of what is is capable of:

See the Pen Mole :: property curves example by LegoMushroom (@sol0mka) on CodePen.

bodymovin

If you happen to be a video person before you became a web person (or you're still both) perhaps you have experience working in Adobe After Effects, which is all about creating "incredible motion graphics and visual effects". The bodymovin library exports After Effects into SVG, including plenty of hot morphing action. Here's a great demo:

See the Pen svg jou jou monster by kittons (@airnan) on CodePen.

The Many Tools for Shape Morphing is a post from CSS-Tricks

Think you know the top web browsers?

Css Tricks - Sat, 04/22/2017 - 5:19am

If I had to blindly guess about global marketshare, I would have gotten it wrong. I probably would have forgotten about UC browser (kind of the point of Peter O'Shaughnessy's article) that's so huge in Asia. I would have guessed Firefox has a slight edge on Safari (turns out Firefox is half the share of Safari), and that Edge would be outpacing IE by now (also only half).

This is good dinner party conversation fodder, but I wouldn't base any major decision making on it. The only stats that matter at your websites stats.

Here's this sites, in the last 7 days.

There is always the chicken-or-egg conundrum though. If you support a browser that you didn't before, doesn't it stand to reason the numbers would go up for it? The time-on-site and bounce rate stuff would get better, anyway.

Direct Link to ArticlePermalink

Think you know the top web browsers? is a post from CSS-Tricks

Join Typekit at Typographics!

Nice Web Type - Fri, 04/21/2017 - 11:18am

Now in its third year, June’s Typographics Conference announced its final lineup this week. We can’t wait to attend and hear so many excellent speakers from the type and graphic design industries. We’re once again sponsoring the conference, so please come and say hello if you see our team around Cooper Union.

Just for friends of Typekit, we have a conference discount code for $50 off. Use promo code ADOBE_50 when registering for Typographics.

We’ll be sponsoring a lunch workshop with our friends at Type Network on Friday, June 16 and Saturday, June 17 for students and early-career folks to chat about networking and mentorship in the type industry. Stay tuned to attendee communications for more details and a link to register.

In addition to the main program, the conference will once again feature an array of workshops and tours for attendees, as well as TypeLab happening June 15-19.

While you’re in New York…

…and if you’re in town around that time (or already local!), we are presenting a private screening of the Graphic Means documentary at the SVA Theatre on Tuesday, June 13.

The screening will be open to members of several NYC organizations: the Type Directors Club, Advertising Production Club of New York, Graphic Communications Scholarship Foundation, Art Directors Club, the ONE Club, The Navigators, Book Industry Guild of NY, Printing Industries Alliance, Women’s National Book Association/NY Chapter, Book Industry Study Group, Book Manufacturers’ Institute, and the Media Technology & Design Industry Advisory Commission.

Learn more about the Graphic Means documentary, and if you can’t make this screening stay tuned for more opportunities!


Persistence Has a Weird Way of Getting Things Done

Css Tricks - Fri, 04/21/2017 - 1:37am

I like to think of myself as having a decent amount of persistence. But of course, life is complicated. Sometimes I have it and sometimes I don't. I have in some areas and not in others. C'est la vie. Here's two very short things that I've written up along this theme.

I once wrote this about it, in a little article I called Mediocre Ideas, Showing Up, and Persistence:

Truly great ideas are rare. Jokers like us will probably never have one. That’s OK. We have mediocre ones all the time and they work just fine. I once had an idea to start a blog about CSS. I sucked at writing. I sucked at designing. The vibe at the time was that everything important about CSS had already been written. Nobody told me.

I didn't just have the idea, I did it. That's the showing up part. Hands on the keyboard, go. I barely knew what I was doing. I stumbled through even following simple walkthroughs on how to install the software. Executing your ideas is never overly comfortable.

Then never stop. Don't get distracted by some other idea and prance away to that tomorrow. Keep doing it until you’ve done everything you set out to do and everyone and their mom knows it.

Here's another related story that I shared in the newsletter a little while back.

My neighbor was out working on her car the other day, and I stopped over to help. Like "pass me the screwdriver" kinda help, as I certainly have no car repair expertise.

The issue was that her rear running lights were out. After dismantling the fixtures (through the trunk), she rules out burnt out bulbs (she replaced them anyway, cause they are cheap, and just to be sure). The next stop was the fuse box, and sure enough, one of the fuses that seemed to be part of the rear lights circuit was burnt out. We replaced the fuse, but turning on the car instantly blew the fuse again. We tried a few times with the same result. She tried a higher-amp fuse, still blew out.

"It's a short." She diagnosed. Meaning the power from the battery was traveling along a circuit with no resistance. Some metal-on-metal happening somewhere unintended. We're already over an hour into this job, at least, and this is pretty demoralizing. But, she remembered she also recently installed a new car stereo in the dashboard. It was a few weeks ago, but still.

After dismantling the dashboard to get behind the newly-installed car stereo, she found some dangling orange wires that weren't capped off. Looking closely, it appeared as if the might have been sparking a bit! Singed edges, some browning. After capping these wires off, stopping the potential short, we were able to turn the car on without it blowing the fuse, and the rear lights came right on.

There are lessons abound in this story:

  • I probably wouldn't have even tried to fix this myself. There is time and money to be gained by tackling problems like this yourself.
  • Diagnosing problems involves taking things apart and looking at smaller and smaller parts until you isolate the problem.
  • Sometimes to understand the problem, you need to use your schoolin'. You can't fix a short unless you know what a short is.
  • If it's a new problem, there is a high chance it's related to the last time you made changes.
  • Throwing more power at a problem rarely fixes it.
  • Persistence is powerful. Even if I tried tackling a problem like this myself, I likely would have given up at any number of frustrating points along the way. Her persistence won the day.

I'll let you make the connections to development work yourself.

Persistence Has a Weird Way of Getting Things Done is a post from CSS-Tricks

Legally Binding Electronic Signatures with eversign

Css Tricks - Thu, 04/20/2017 - 3:24am

There are few things more obnoxiously tedious than being asked to sign a document over email, where they tell you to print it, sign it, scan it, and email it back. One time I Photoshopped my signature onto a document, and they were able to tell somehow and made me go through the whole rigamarole instead.

We're working with highly sophisticated computers here, can't I sign this thing with the web somehow? Yes, you can! As long as the company asking is using eversign, that is.

Companies of any size can use eversign, from individual freelancers to medium-sized businesses to mega corporations. You upload your documents (like a PDF contract, rental agreement, or anything else you need a legally-binding signature on) and use their wonderfully nice Document Builder UI to indicate the areas that information or signatures from who the document is being sent to.

Here's a little video of how that works:

Then you can prepare the document to be signed by particular people, and send it to them. They can then complete and sign it and send it back to you in seconds:

What if you already have a system for preparing and handling documents? Great, eversign has a modern and powerful REST JSON API for preparing documents (and everything else you can do on eversign).

Direct Link to ArticlePermalink

Legally Binding Electronic Signatures with eversign is a post from CSS-Tricks

The Power of Custom Directives in Vue

Css Tricks - Thu, 04/20/2017 - 3:14am

When you're initially learning a JavaScript framework, it feels a little like being a kid in a candy store. You take in everything available to you, and right off the bat, there are things that will make your life as a developer easier. Inevitably though, we all reach a point working with a framework where we have a use-case that the framework doesn't cover very well.

The beautiful thing about Vue is that it's incredibly feature-rich. But even if you have an edge case not covered by the framework, it's got your back there as well, because you can quite easily create a custom directive.

What are directives?

I've written a post here on directives in my guide on Vue.js, but let's do a refresher.

Directives are tiny commands that you can attach to DOM elements. They are prefixed with v- to let the library know you're using a special bit of markup and to keep syntax consistent. They are typically useful if you need low-level access to an HTML element to control a bit of behavior.

Some directives you might already be familiar with if you've worked with Vue (or Angular, for that matter) are v-if, v-else, v-show, etc. We'll go into some of the foundations, but if you'd rather read through the examples instead, you could scroll down the page a bit and probably still understand the concepts.

Here are some ways to use a directive, along with an example counterpart. These examples are not prescriptive, they're just use-cases. The word example here is in place of the actual directive.

v-example - this will instantiate a directive, but doesn't accept any arguments. Without passing a value, this would not be very flexible, but you could still hang some piece of functionality off of the DOM element.

v-example="value" - this will pass a value into the directive, and the directive figures out what to do based off of that value.

<div v-if="stateExample">I will show up if stateExample is true</div>

v-example="'string'" - this will let you use a string as an expression.

<p v-html="'<strong>this is an example of a string in some text</strong>'"></p>

v-example:arg="value" - this allows us to pass in an argument to the directive. In the example below, we're binding to a class, and we'd style it with an object, stored separately.

<div v-bind:class="someClassObject"></div>

v-example:arg.modifier="value" - this allows us to use a modifier. The example below allows us to call preventDefault() on the click event.

<button v-on:submit.prevent="onSubmit"></button> Understanding Custom Directives

Now that we see all the ways we can use directives, let's break down how we would implement them with a custom directive we author ourselves. A nice example of something you might use a custom directive for is a scroll event, so let's see how we'd write that.

At it's very base, this is how we would create a global directive. (but it doesn't do anything - yet!) - it just creates the directive.

Vue.directive('tack');

On the element itself, it would look like:

<p v-tack>This element has a directive on it</p>

There are a few hooks available to us, and each one has the option of a few arguments. The hooks are as follows:

  • bind - This occurs once the directive is attached to the element.
  • inserted - This hook occurs once the element is inserted into the parent DOM.
  • update - This hook is called when the element updates, but children haven't been updated yet.
  • componentUpdated - This hook is called once the component and the children have been updated.
  • unbind - This hook is called once the directive is removed.

Personally, I find bind and update the most useful of the five.

Each of these have el, binding, and vnode arguments available to them, with the exception of update and componentUpdated, which also expose oldVnode, to differentiate between the older value passed and the newer value.

el, as you might expect, is the element the binding sits on. binding is an object which contains arguments that are passed into the hooks. There are many available arguments, including name, value, oldValue, expression, arg, and modifiers. vnode has a more unusual use-case, it's available in case you need to refer directly to the node in the virtual DOM. Both binding and vnode should be treated as read-only.

Building a Custom Directive

Now that we've broken that down, we can start to look at how we'd use a custom directive in action. Let's build off of that first example with what we just covered to make it more useful:

Vue.directive('tack', { bind(el, binding, vnode) { el.style.position = 'fixed' } });

And on the HTML itself:

<p v-tack>I will now be tacked onto the page</p>

This is OK, but it's not very flexible until we pass a value into it and update it or reuse it on the fly. Let's decide how far from the top we'd like to fix the element to:

Vue.directive('tack', { bind(el, binding, vnode) { el.style.position = 'fixed' el.style.top = binding.value + 'px' } }); <div id="app"> <p>Scroll down the page</p> <p v-tack="70">Stick me 70px from the top of the page</p> </div>

See the Pen.

Let's say I wanted to now differentiate between whether or not we're offseting the 70px from the top or the left. We could do that by passing an argument:

<p v-tack:left="70">I'll now be offset from the left instead of the top</p> Vue.directive('tack', { bind(el, binding, vnode) { el.style.position = 'fixed'; const s = (binding.arg == 'left' ? 'left' : 'top'); el.style[s] = binding.value + 'px'; } });

See the Pen.

You can use more than one value, as well. You could do so the same way you would for regular directives:

<p v-tack="{ top: '40', left: '100' }">Stick me 40px from the top of the page and 100px from the left of the page</p>

And then the directive would be rewritten to work with both:

Vue.directive('tack', { bind(el, binding, vnode) { el.style.position = 'fixed'; el.style.top = binding.value.top + 'px'; el.style.left = binding.value.left + 'px'; } });

See the Pen.

We can also write something more complex where we can create and modify methods based on our custom directives. Here, we'll do a waypoints-like example, where we can create an animation that fires off a particular scroll event with a small amount of code:

Vue.directive('scroll', { inserted: function(el, binding) { let f = function(evt) { if (binding.value(evt, el)) { window.removeEventListener('scroll', f); } }; window.addEventListener('scroll', f); }, }); // main app new Vue({ el: '#app', methods: { handleScroll: function(evt, el) { if (window.scrollY > 50) { TweenMax.to(el, 1.5, { y: -10, opacity: 1, ease: Sine.easeOut }) } return window.scrollY > 100; } } }); <div class="box" v-scroll="handleScroll"> <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. A atque amet harum aut ab veritatis earum porro praesentium ut corporis. Quasi provident dolorem officia iure fugiat, eius mollitia sequi quisquam.</p> </div>

See the Pen.

In these Pens, we're keeping everything simple so that you can see it easily. In an actual app, you can build out really nice custom and flexible customized directives available for your whole team.

In an actual build process, I would place the directive code in the `main.js` file that lives at the root of the `src` directory (if you're using something like the Vue-cli build) so that `App.vue` and all of the subsequent .vue files in the components directory will have access to it. There are other ways of working with it as well, but I've found this to be the most flexible implementation for the whole app.

If you'd like to learn more about the Vue framework, check out our guide.

The Power of Custom Directives in Vue is a post from CSS-Tricks

When Does a Project Need React?

Css Tricks - Thu, 04/20/2017 - 2:21am

You know when a project needs HTML and CSS, because it's all of them. When you reach for JavaScript is fairly clear: when you need interactivity or some functionality that only JavaScript can provide. It used to be fairly clear when we reached for libraries. We reached for jQuery to help us simplify working with the DOM, Ajax, and handle cross-browser issues with JavaScript. We reached for underscore to give us helper functions that the JavaScript alone didn't have.

As the need for these libraries fades, and we see a massive rise in new frameworks, I'd argue it's not as clear when to reach for them. At what point do we need React?

I'm just going to use React as a placeholder here for kinda large JavaScript framework thingies. Vue, Ember, Svelte... whatever. I understand they aren't all the same, but when to reach for them I find equally nebulous.

Here's my take.

? Because there is lots of state.

Even "state" is a bit of a nebulous word. Imagine things like this:

  • Which navigation item is active
  • Whether a button is disabled or not
  • The value of an input
  • Which accordion sections are expanded
  • When an area is loading
  • The user that is logged in and the team they belong to
  • Whether the thing the user is working on is published, or a draft

"Business logic"-type stuff that we regularly deal with. State can also be straight up content:

  • All the comments on an article and the bits and bobs that make them up
  • The currently viewed article and all its metadata
  • An array of related articles and the metadata for those
  • A list of authors
  • An an activity log of recent actions a user has taken

React doesn't help you organize that state, it just says: I know you need to deal with state, so let's just call it state and have programmatic ways to set and get that state.

Before React, we might have thought in terms of state, but, for the most part, didn't manage it as a direct concept.

Perhaps you've heard the phrase "single source of truth"? A lot of times we treated the DOM as our single source of truth. For example, say you need to know if a form on your website is able to be submitted. Maybe you'd check to see if $(".form input[type='submit']).is(":disabled") because all your business logic that dealt with whether or not the form could be submitted or not ultimately changed the disabled attribute of that button. So the button became this defacto source of truth for the state of your app.

Or say you needed to figure of the name of the first comment author on an article. Maybe you'd write $(".comments > ul > li:first > h3.comment-author).text() because the DOM is the only place that knows that information.

React kinda tells us:

  1. Let's start thinking about all that stuff as state.
  2. I'll do ya one better: state is a chunk of JSON, so it's easy to work with and probably works nicely with your back end.
  3. And one more even better: You build your HTML using bits of that state, and you won't have to deal with the DOM directly at all, I'll handle all that for you (and likely do a better/faster job than you would have.)
? To Fight Spaghetti.

This is highly related to the state stuff we were just talking about.

"Spaghetti" code is when code organization and structure has gotten away from you. Imagine, again, a form on your site. It has some business logic stuff that specifically deals with the inputs inside of it. Perhaps there is a number input that, when changed, display the result of some calculation beside it. The form can also be submitted and needs to be validated, so perhaps that code is in a validation library elsewhere. Perhaps you disable the form until you're sure all JavaScript has loaded elsewhere, and that logic is elsewhere. Perhaps when the form is submitted, you get data back and that needs logic and handling. Nothing terribly surprising here, but you can see how this can get confusing quickly. How does a new dev on the project, looking at that form, reason out everything that is going on?

React encourages the use of building things into modules. So this form would likely either be a module of its own or comprised of other smaller modules. Each of them would handle the logic that is directly relevant to it.

React says: well, you aren't going to be watching the DOM directly for changes and stuff, because the DOM is mine and you don't get to work with it directly. Why don't you start thinking of these things as part of the state, change state when you need to, and I'll deal with the rest, rerendering what needs to be rerendered.

It should be said that React itself doesn't entirely solve spaghetti. You can still have state in all kinds of weird places, name things badly, and connect things in weird ways.

In my limited experience, it's Redux that is the thing that really kills spaghetti. Redux says: I'll handle all the important state, totally globally, not module-by-module. I am the absolute source of truth. If you need to change state, there is quite a ceremony involved (I've heard it called that, and I like it.) There are reducers and dispatched actions and such. All changes follow the ceremony.

If you go the Redux road (and there are variations of it, of course), you end up with really solid code. It's much harder to break things and there are clear trails to follow for how everything is wired together.

? Lots of DOM management.

Manually handling the DOM is probably the biggest cause of spaghetti code.

  1. Inject HTML over here!
  2. Rip something out over here!
  3. Watch this area for this event!
  4. Bind a new event over here!
  5. New incoming content! Inject again! Make sure it has the right event bindings!

All these things can happen any time from anywhere in an app that's gone spaghetti. Real organization has been given up and it's back to the DOM as the source of truth. It's hard to know exactly what's going on for any given element, so everybody just asks the DOM, does what they need to do, and crosses their fingers it doesn't mess with somebody else.

React says: you don't get to deal with the DOM directly. I have a virtual DOM and I deal with that. Events are bound directly to the elements, and if you need it to do something above and beyond something directly handle-able in this module, you can kind of ceremoniously call things in higher order modules, but that way, the breadcrumb trail can be followed.

Complicated DOM management is another thing. Imagine a chat app. New chat messages might appear because a realtime database has new data from other chatters and some new messages have arrives. Or you've typed a new message yourself! Or the page is loading for the first time and old messages are being pulled from a local data store so you have something to see right away. Here's a Twitter thread that drives that home.

? Just because. It's the new hotness.

Learning something for the sake of learning something is awesome. Do that.

Building a project for clients and real human being users requires more careful consideration.

A blog, for example, probably has none of the problems and fits none of the scenarios that would make React a good fit. And because it's not a good fit, it's probably a bad fit, because it introduces complicated technology and dependencies for something that doesn't call for it.

And yet, gray area. If that blog is a SPA ("Single Page App", e.g. no browser refreshing) that is built from data from a headless CMS and had fancy server-side rendering... well maybe that is React territory again.

The web app CMS that makes that blog? Maybe a good choice for React, because of all the state.

? I just like JavaScript and want to write everything in JavaScript.

People get told, heck, I've told people: learn JavaScript. It's huge. It powers all kinds of stuff. There are jobs in it. It's not going anyway.

It's only in recent web history that it's become possible to never leave JavaScript. You got Node.js on the server side. There are loads of projects that yank CSS out of the mix and handle styles through JavaScript. And with React, your HTML is in JavaScript too.

All JavaScript! All hail JavaScript!

That's cool and all, but again, just because you can doesn't mean you should. Not all projects call for this, and in fact, most probably don't.

?? That's what I know.

(There are decent emojis for YES and NO, but MAYBE is tougher!)

You're learning. Awesome. Everybody is. Keep learning. The more you know the more informed decisions you can make about what tech to use.

But sometimes you gotta build with what you know, so I ain't gonna ding ya for that.

?? That's where the jobs are.

Not everybody has a direct say in what technology is used on any given project. Hopefully, over time, you have influence in that, but that takes time. Eden says she spent 2 years with Ember because that's where the jobs were. No harm in that. Everybody's gotta get paid, and Ember might have been a perfect fit for those projects.

When Does a Project Need React? is a post from CSS-Tricks

Total HTML Agnosticism

Css Tricks - Wed, 04/19/2017 - 9:43am

A couple of good posts on technology agnosticism lately.

Brad Frost says the design system itself is higher level than any particular technology:

... it doesn't bet the farm on any one technology, the system is able to adapt to inevitable changes to tools, technologies, and trends.

Jonathan Snook thinks Mustache is good choice for otherwise technologically agnostic templating:

I like it because of its simplicity and because it requires the heavy work with the data to be done before it sees a template.

Here's a slide I used at a recent workshop:

What I was mostly referring to is total HTML agnosticism. It doesn't matter (to me) where the HTML comes from.

  • Did Drupal produce the HTML? Fine.
  • Is the HTML in JSX? Fine.
  • Is it a Mustache template? Fine.
  • Am I editing totally raw HTML like elite hacker? Fine.
  • Am I piecing together partials in Nunjucks. Fine.
  • Is this a Rails ERB thing? Fine.

What I care about is the final output. Whatever creates the final HTML, it's on me to make it clean, manageable, accessible, semantic, and performant.

To be clear, I do care about the technology stack. I'm aware of the benefits and tradeoffs of different technologies (or at least I try to be aware, and can do research). It's just that when I have my front-end developer hat on, the thing I care most about is that final chunk of HTML that hits the browser.

So a minor side note, I bet a nickel knowing HTML well and being a generally agnostic developer will make you more employable.

Total HTML Agnosticism is a post from CSS-Tricks

The Can-Do’s of CodePen Projects

Css Tricks - Wed, 04/19/2017 - 4:32am

We just recently launched Projects, the latest big feature over on CodePen. It's quite a bit different than the Pen Editor, so let's take a look at all the things it can do!

A Complete File System, and Complete HTML Files

With CodePen Projects, you get a sidebar of files for you to put whatever files you like.

That's different than the Pen Editor on CodePen, which only gives you the HTML, CSS, and JavaScript editor to work with. While that's super convenient for many types of demos, it can be limiting. What if you need multiple HTML files to link between? What if you need partials to include as needed? What if you need to upload other files to work with just for this demo?

With Projects, you have complete control over the entire file structure. Create files and folders as needed. HTML files are complete documents, so you aren't limited to our boilerplate HTML structure like you are in the Pen Editor.

Drag and Drop Uploading

If you have file on your local machine that you'd like to upload and work with on CodePen, it couldn't be easier. The sidebar of a Project is drag-and-drop ready!

This makes it easy, for example, to export a repo and move it over to CodePen to play with. These files could be HTML, CSS, JavaScript, any of the preprocessor types we support, images, fonts, and lots of other types of assets. It does limit the upload of some file types (for example, back-end languages like PHP) to make clear what CodePen Projects does and doesn't support.

Process Sass (or many other Preprocessors) with Partials

Do you like to keep your variable declarations in a separate file? Perhaps you break out your layout CSS into its own file as well. Working with partials is a super useful part of any CSS preprocessor!

This is an example of how I like to work:

You can view the compiled version by opening the "processed" file in the sidebar. It prevents you from editing the processed file though, as you'd lose changes next time the preprocessor compiled.

Build Multi-Page sites with HTML Includes

CodePen Projects offers two preprocessing languages that can do HTML includes: Pug and Nunjucks.

In Pug, you use include file.pug (where `file.pug` is the file path to any other Pug file) and it will grab that file and include it.

This makes it easy to piece together parts of files into complete HTML documents, making multi-page sites much easier. You can also weave together HTML using the block syntax which allows you to make a template in which any file "extending" it can pass in chunks of content that will replace those areas.

In Nunjucks, the syntax is like {% include "components/mini-header.njk" %}, and works exactly the same way. It goes and gets that file and plunks it into place in the file that called it. Nunjucks isn't whitespace-dependent like Pug either, it's just an extension of regular HTML.

Make a Pattern Library with Nunjucks

This one probably deserves and entire article (soon!), but speaking of Nunjucks, Nunjucks has the concept of a "Macro", which is a bit like an include, only you can pass parameters to it. It's a wonderfully simple syntax:

Now let's say you want to load up that Macro and use it elsewhere.

{% import "pattern/_colors.njk" as macroColors %}

Say we're building out color swatches for our pattern library. We can define the colors (with notes) as an array, then loop through it, calling the Macro with the data.

That's powerful stuff! Call this HTML, passing these parameters, and sprinkle those parameters through the HTML however I need them. That could be useful for all kinds of stuff. Imagine a modal dialog, in which you need to pass in the header and content, but also classes to define the style, or values to determine if certain buttons should show or not.

Use ES6 Includes via Webpack

Let's say I have a little helper function that you pass a string of HTML and it returns a real DOM node. In ES6, we can export a function like that so that other JavaScript files can import it as a dependency:

export function getNodes(str) { return new DOMParser().parseFromString(str, 'text/html').body.childNodes; }

Then in any file that wants to use it:

import { getNodes } from "./helpers";

That's just starting to land natively in browsers, but for the most part, that kind of thing is handled by Webpack bundling it all up. And that's also generally paired with Babel, so you can go all-in on the ES6 syntax.

You're free to work either way in CodePen Projects. Leave it alone if you want the browsers to do things natively, or flip the switch and turn on Webpack and Babel processing:

You can write in Typescript as well. We've seen some fancy-dancing using SystemJS with Typescript and ultimately importing dependencies right off npm.

Auto-formatted Markdown

Does your project have a README? Perhaps a TODO list for yourself? Not only can you write in Markdown with CodePen Projects, but the preview window will apply some style to it so you can look at it in a format much like any other blog post on CodePen.

You can also open the processed version of the file to see the processed HTML without any other influence.

Have a Development version and Deployed version of your Project

At any time, you can click the Deploy and open up this dialog which allows you to deploy your Project out to a special URL:

That is a public URL that you can share with anyone. It has zero CodePen UI or influence whatsoever. It's just a straight up copy of your files, hosted for the world to see. You can use it for testing, showing clients, or whatever you like.

An important bit here is that the works just like real world deployment does. You can continue to work on your Project, saving it and changing it to your heart's content, and that doesn't affect the deployed version. It becomes your development version, effectively. Then, again at any time, you can deploy.

There are no limits to how many times you deploy, only how many different Projects you have deployed.

Use a Custom Domain Name for your Project

You probably noticed the URL is a little funky for deployed websites. We hope someday we'll allow you to customize that, but what is here today (and even better really) is the ability to use a custom domain (that you own) to point to your deployed Project.

It's a matter of changing DNS "A Records" (documentation) to point to a couple of special IP addresses we've set up for this.

After that propagates and I've deployed, my Project is available at my custom domain!

Notice that example is HTTPS. That doesn't come automatically, but in this case I've set up CloudFlare, changed my domain's nameservers to point to CloudFlare, then the A Records at Cloudflare to point to the CodePen IP's. Free HTTPS! Which means I can do stuff like use modern JavaScript stuff that requires HTTPS, like getUserMedia or register a Service Worker.

Use Vim Key Bindings

Sure can. It's a user setting on CodePen that follows you into all the different editors. You can pick key bindings that mimic Sublime Text too, if you're partial to that.

I point this out as just one tiny little comfort feature of working on CodePen. There are so many others, like:

  • Autocomplete
  • Emmet
  • Choice of syntax highlighting theme
  • Choice of tabs/spaces and how deep
  • Choice of font and size
  • Line wrapping (or not)
  • Line numbers (or not)
  • Matching brackets (or not)
  • And the list goes on! Lots of options for setting up the code editor just how you like
Start with a Template

When you kick off a brand new Project, we've prefilled the sidebar with a bunch of choices:

By no means do you have to pick a template from this list, but it might help you get a feel for things or speed things up if what you want to build uses these technologies. We're hoping to have lots of templates, eventually, for you to get started with. If you have an interesting one you've built, let us know!

You can also easily build your own templates. On any Project, flip on the template toggle in settings:

Now that template is available whenever you start a new Project:

And of course... any public Project you find on CodePen you can fork!

... and (wait for it) So Much More

Here's an incomplete list of things I didn't get a chance to tell you about: searching for external assets, tidying your code, analyzing your code, exporting, sharing (gasps for air), global assets, keyboard shortcuts, or all the different views!

I'll leave you by encourging you to check out our landing page for Projects and checking out the documentation.

The Can-Do’s of CodePen Projects is a post from CSS-Tricks

Syndicate content
©2003 - Present Akamai Design & Development.