Web Standards

Revisiting prefers-reduced-motion, the reduced motion media query

Css Tricks - Tue, 04/30/2019 - 5:13am

Two years ago, I wrote about prefers-reduced-motion, a media query introduced into Safari 10.1 to help people with vestibular and seizure disorders use the web. The article provided some background about the media query, why it was needed, and how to work with it to avoid creating disability-triggering visual effects.

The article was informed by other people’s excellent work, namely Orde Saunders’ post about user queries, and Val Head’s article on web animation motion sensitivity.

We’re now four months into 2019, and it makes me happy to report that we have support for the feature in all major desktop browsers! Safari was first, with Firefox being a close second. Chrome was a little late to the party, but introduced it as of version 74.

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

DesktopChromeOperaFirefoxIEEdgeSafari74No63NoNo10.1Mobile / TabletiOS SafariOpera MobileOpera MiniAndroidAndroid ChromeAndroid Firefox10.3NoNo67NoNo

While Microsoft Edge does not have support for prefers-reduced-motion, it will become Chrome under the hood soon. If there’s one good thing to come from this situation, it’s that Edge’s other excellent accessibility features will (hopefully) have a good chance of being back-ported into Chrome.

Awareness

While I’m happy to see some websites and web apps using the media query, I find that it’s rare to encounter it outside of places maintained by people who are active in CSS and accessibility spaces. In a way, this makes sense. While prefers-reduced-motion is relatively new, CSS features and functionality as a whole are often overlooked and undervalued. Accessibility even more so.

It’s tough to blame someone for not using a feature they don’t know exists, especially if it’s relatively new, and especially in an industry as fast-paced as ours. The deck is also stacked in terms of what the industry prioritizes as marketable, and therefore what developers pay attention to. And yet, prefers-reduced-motion is a library-agnostic feature that ties into Operating System-level functionality. I’m pretty sure that means it’ll have some significant staying power in terms of reward for time spent for skill acquisition.

Speaking of rewards, I think it’s also worth pointing out the true value prefers-reduced-motion represents: Not attracting buzzword-hungry recruiters on LinkedIn, but improving the quality of life for the people who benefit from the effect it creates. Using this media query could spare someone from having to unnecessarily endure a tremendous amount of pain for simply having the curiosity to click on a link or scroll down a page.

The people affected

When it comes to disability, many people just assume “blind people.” The reality is that disabilities are a complicated and nuanced topic, one that is surprisingly pervasive, deeply personal, and full of unfortunate misconceptions. It's also highly variable. Different people are affected by different disability conditions in different ways — extending to a wide gamut of permanent, temporary, environmental, and situational concerns. Multiple, compounding conditions can (and do) affect individuals, and sometimes what helps one person might hinder another. It’s a difficult, but very vital thing to keep in mind.

If you have a vestibular disorder or have certain kinds of migraine or seizure triggers, navigating the web can be a lot like walking through a minefield — you’re perpetually one click away from activating an unannounced animation. And that’s just for casual browsing.

If you use the web for work, you might have no choice but to endure a web app that contains triggering animations multiple times a week, or even per day or hour. In addition to not having the autonomy to modify your work device, you may also not have the option to quickly and easily change jobs — a privilege easily forgotten when you’re a specialized knowledge worker.

It’s a fallacy to assume that a person is aware of their vestibular disorder, or what triggers it. In fact, sometimes the initial triggering experience exacerbates your sensitivity and makes other parts of a design difficult to use. Facundo Corradini shares his experience with this phenomenon in his article, “Accessibility for Vestibular Disorders: How My Temporary Disability Changed My Perspective.”

Not all assistive technology users are power users, so it’s another fallacy to assume that a person with a vestibular disorder is aware of, or has the access rights to enable a motion-reducing Operating System setting or install a browser extension.

Think of someone working in a large corporation who has to use a provisioned computer with locked-down capabilities. Or someone who isn’t fully aware of what of their tablet is capable of doing past browsing social media, watching video, and messaging their family and friends. Or a cheap and/or unorthodox device that will never support prefers-reduced-motion feature — some people purchase discontinued devices such as the Windows Phone specifically because their deprecation makes them affordable.

Do these people deserve to be hurt because of their circumstances? Of course not.

Considering what’s harmful

You can tie harm into value, the same way you can with delight. Animation intended to nudge a person towards a signup could also drive them away. This kind of exit metric is more difficult to quantify, but it definitely happens. Sometimes the harm is even intentional, and therefore an easier datapoint to capture — what you do with that information is a whole other issue.

If enough harm happens to enough people, it affects that certain something we know as branding. This effect doesn’t even need to be tied to a disability condition. Too much animation, applied to the wrong things in the wrong way will drive people away, even if they can’t precisely articulate why.

You also don’t know who might be on the receiving end, or what circumstances they’re experiencing the moment they load your website or web app. We can’t — and shouldn’t — know this kind of information, either. It could be a prospective customer, the employee at a venture capitalist firm tasked with evaluating your startup, or maybe even your new boss.

We also don’t need to qualify their relationship to us to determine if their situation is worth considering — isn’t it enough to just be proactively kind?

Animation is progressive enhancement

We also need to acknowledge that not every device that can access the web can also render animation, or render animation smoothly. When animation is used on a low-power or low quality device that “technically” supports it, the overall user experience suffers. Some people even deliberately seek this experience out as a feature.

Devices may also be set to specialized browsing modes to allow people to access your content in alternate ways. This concept is known as being robust, and is one of the four high-level principles that govern the guidelines outlining how to craft accessible experiences.

Animation might not always look the way you intend it in these modes. One example would be when the viewport is zoomed and the animation isn’t built using relative units. There’s a non-trivial chance important parts might be pushed out of the viewport, leaving the animation appearing as a random collection of flickering bits. Another example of a specialized browsing mode might be Reader Mode, where the animation may not appear at all.

Taking it to code

Considering all this, I’m wondering if there are opportunities to help web professionals become more aware of, and therefore more considerate of the downsides of poorly conceived and implemented animation.

Maybe we proactively incorporate a media query high up in the cascade to disable all animation for those who desire it, and for those who have devices that can’t support it. This can be accomplished by targeting anything where someone has expressed a desire for a low-to-no-animation experience, or any device that has a slow screen refresh rate.

The first part of the query, targeting low-to-no-animation, is done via prefers-reduced-motion. The second, targeting a screen with a low refresh rate, uses update. update is a new media feature that allows us to “query the ability of the output device to modify the appearance of content once it has been rendered.”

@media screen and (prefers-reduced-motion: reduce), (update: slow) { * { animation-duration: 0.001ms !important; animation-iteration-count: 1 !important; /* Hat tip Nick/cssremedy (https://css-tricks.com/revisiting-prefers-reduced-motion-the-reduced-motion-media-query/#comment-1700170) */ transition-duration: 0.001ms !important; } }

This code forces all animation that utilizes a declaration of animation-duration or transition-duration to conclude at a rate that is imperceptible to the human eye. It will work when a person has requested a reduced motion experience, or the device has a screen with a slow refresh rate, say e-ink or a cheap smartphone.

Retaining the animation and transition duration also ensures that any functionality that is tied to CSS-based animation will activate successfully (unlike using a declaration of animation: none), while still preventing a disability condition trigger or creating rendering lag.

This declaration is authored with the intent of introducing some intentional friction into our reset styles. Granted, it’s not a perfect solution, but it does drive at a few things:

  1. Increasing the chances of developers becoming aware of the two media features, by way of making them present in the cascade of every inspected element.
  2. Providing a moment to consider why and how animation will be introduced into a website or web app, and what the experience should be like for those who can’t or don’t want to experience it.
  3. Encouraging developers who are less familiar with CSS to think of the cascade in terms of components and nudge them towards making more easily maintainable stylesheets.
Animation isn’t unnecessary

In addition to vestibular disorders and photosensitive conditions, there’s another important aspect of accessibility we must consider: cognitive disabilities.

Cognitive disabilities

As a concern, the category is wide and often difficult to quantify, but no less important than any other accessibility discipline. It is also far more prevalent. To expand on this some, the World Health Organization reports an estimated 300 million people worldwide are affected by depression, a temporary or permanent, environmental and/or biological condition that can significantly impair your ability to interact with your environment. This includes interfering with your ability to understand the world around you.

Animation can be a great tool to help combat some forms of cognitive disability by using it to break down complicated concepts, or communicate the relationship between seemingly disparate objects. Val Head’s article on A List Apart highlights some other very well-researched benefits, including helping to increase problem-solving ability, recall, and skill acquisition, as well as reducing cognitive load and your susceptibility to change blindness.

Reduce isn’t necessarily remove

We may not need to throw the baby out with the bathwater when it comes to using animation. Remember, it’s prefers-reduced-motion, not prefers-no-motion.

If we embrace the cascade, we can work with the animation reset code described earlier on a per-component basis. If the meaning of a component is diminished by removing its animation altogether, we could slow down and simplify the component’s animation to the point where the concept can be communicated without potentially being an accessibility trigger.

If you’re feeling clever, you might even be able to use CSS Custom Properties to help achieve this in an efficient way. If you’re feeling extra clever, you could also use these Custom Properties for a site-wide animation preferences widget.

In the following code sample, we’re defining default properties for our animation and transition durations, then modifying them based on the context they’re declared in:

/* Set default durations */ :root { --animation-duration: 250ms; --transition-duration: 250ms; } /* Contextually shorten duration length */ @media screen and (prefers-reduced-motion: reduce), (update: slow) { :root { --animation-duration: 0.001ms !important; --transition-duration: 0.001ms !important; } } @media screen and (prefers-reduced-motion: reduce), (update: slow) { /* Remove duration for all unknown animation when a user requests a reduced animation experience */ * { animation-duration: var(--animation-duration); animation-iteration-count: 1 !important; transition-duration: var(--animation-duration); } } /* Update the duration when animation is critical to understanding and the device can support it */ @media screen and (prefers-reduced-motion: reduce), (update: fast) { .c-educational-concept { /* Set a new animation duration scoped to this component */ --animation-duration: 6000ms !important; ... animation-name: educational-concept; /* Use the scoped animation duration */ animation-duration: var(--animation-duration); } }

However, trying to test the effectiveness of this slowed-down animation puts us in a bit of a pickle: there’s no real magic number we can write a test against.

We need to have a wide representation of people who are susceptible to animation-based disability triggers to sign off on it being safe, which unfortunately involves subjecting them to something that may potentially not be. That’s a huge ask.

A better approach is to ask about what kinds of animation have been triggers for them in the past, then see if what they describe matches what we’ve made. This approach also puts the onus on yourself, and not the person with a disability, to do the work to provide accommodation.

If you’re having trouble finding people, ask your friends, family, and coworkers — I’m sure there’s more people out there than you think. And if you need a good starting point for creating safer animation, I once again urge you to read Val’s article on A List Apart.

Neurodivergence

There’s a lot to unpack here, and I’m not the most qualified person to talk about it. Here’s what my friend Shell Little, an Accessibility Specialist at Wells Fargo DS4B, has to say about it:

Web animation as it relates to Neurodivergence (ND) can be a fantastic tool to guide users to solidify meaning and push understanding. The big issue is the same animation that can assist one group of ND users can create a barrier for another. As mentioned by Eric, Neurodivergence is a massive group of people with a vast range of abilities and covers a wide variety of cognitive disabilities including but not limited to ADHD, autism, dyslexia, epilepsy, dyscalculia, obsessive-compulsive disorder, dyspraxia, and Tourette syndrome.

When speaking about motion on the web it’s important we think specifically about attention-related disabilities, autism, and sensory processing disorders that are also closely linked to both. These groups of people, who coincidentally includes me, are especially sensitive to motion as it relates to understanding information and interacting with the web as a whole. Animations can easily overwhelm, distract, and frustrate users who are sensitive to motion and from personal experience, it can even do all three at once.

Because so many people are affected by motion and animation on the web the W3C’s WCAG have a criterion named Pause, Stop, Hide that is specifically written to guide content creators on how to best create accessible animations. My main issues with this guideline are, it only applies to animations that last longer than 5 seconds and motion that is deemed essential is exempt from the standard. That means a ton of animations that can create barriers such as distraction, dizziness, and even harm are out there in the wild.

It makes sense, as Eric mentioned, that we can’t get rid of all animation. Techniques such as spinners let users know the page is still working on the task it was given, and micro-interactions help show progression. But depending on someone’s brain, the things that are helpful at lunch can be a barrier later that night. Someone’s preferences and needs shift throughout their day, and that’s the beauty of prefers-reduced-motion. It has the potential to be what fills the gaps left by Pause, Stop, Hide and allow users to decide when they do or do not want to have motion. That right there is priceless to someone like me.

As someone with an attention-related disability, an interaction I have found to be exceedingly frustrating is autoplay. Many media sharing sites have auto-playing content such as videos, gifs, and ads but because they can be paused, they pass the WCAG standard. That doesn’t mean they aren’t a huge barrier for me as I can’t read any text around them when they are playing. This causes me to have to pause every single moving item I run into. This not only significantly slows me down, and eats away at my limited spoons, but it also derails my task flow and train of thought. Now, it is true some sites — such as Twitter and LinkedIn — have settings to turn autoplay off, but this isn’t true for all sites. This would be a perfect place for prefers-reduced-motion.

In a world where I would be able to determine when and if I want videos to start playing at me, I would be able to get more done with less cognitive strain. prefers-reduced-motion is freedom for me and the millions of people whose brains work like mine. In sum, the absolute best thing we can do for our users who are sensitive to motion is to put a system in place that empowers them to decide when and where animation should be displayed to them. Let the user decide because they will always know their access needs better than we do.

Thanks, Shell!

I don’t hate fun, I just don’t want to hurt people

On my own time, I’m fortunate enough to be able to enjoy animation. I appreciate the large amounts of time and attention involved with making something come alive on the screen, and I’ve definitely put my fair share of time ooh-ing and aah-ing over other people’s amazing work in CodePen. I’ve also watched enough DC Animated Universe to be able to instantly recognize Kevin Conroy’s voice — if you’re looking for even deeper nerd cred, Masaaki Yuasa is a seriously underrated animator.

However, I try to not overly rely on animation as a web professional. There’s a number of factors as to why:

  1. First is simply pushing on awareness of the concerns outlined earlier, as many are unaware they exist. Animation has such a crowd-pleasing gee-whiz factor to it that it’s often quickly accepted into a product without a second thought.
  2. Second is mitigating risk. Not adhering to the Web Content Accessibility Guidelines (WCAG) — including provisions for animation — means your inaccessible website or web app becomes a legal liability. There is now legal precedent for the websites and web apps of private companies being sued, so it’s a powerful metric to weigh your choices against.
  3. Third is user experience. With that gee-whiz factor, people tend to forget that being forced to repeatedly view that super-slick animation over and over again will eventually become a tedious chore. There’s a reason why we no longer make 90s-style loading screens (content warning: high-contrast strobing and flickering, Flash, mimes). If you need a more contemporary example, consider why Netflix lets us skip TV show intros.
  4. Fourth is understanding the lay of the land. While prefers-reduced-motion is getting more support, the majority of it is on desktop browsers, and not mobile. We’re not exactly a desktop-first world anymore, especially if you’re in an underserved community or emerging market. A mobile form factor also may exacerbate vestibular issues. Moving around while using your device means you may lose a fixed reference point, unlike sitting at a desk and staring at a monitor — this kind of trigger is similar to why some of us can get seasick.
  5. The fifth factor is a bit of a subset of the fourth. Animation eats device data and battery, and it’s important to remember that it’s the world wide web, not the wealthy Western web. The person using your service may not have consistent and reliable access to income or power, so you want to get to know your audience before spending their money for them.
The ask

Not everyone who could benefit from prefers-reduced-motion cares about accessibility-related content, so I’d love to see the media query start showing up in the code of more popular sites. The only real way to do this is to spread awareness. Not only of the media query, but more importantly, understanding the nuance involved with using animation responsibly.

CSS-Tricks is a popular website for the frontend industry, and I’m going to take advantage of that. If you feel comfortable sharing, what I would love is to describe what kinds of animation have been problematic for you, in either the comments or on Twitter.

The idea here is we can help build a reference of what kinds of things to be on the lookout for animation-wise. Hopefully, with time and a little luck, we can all help make the web better for everyone.

Thanks to Scott O’Hara, Zach Leatherman, Shell Little, and Geoff Graham for reviewing this article.

The post Revisiting prefers-reduced-motion, the reduced motion media query appeared first on CSS-Tricks.

Perceived Velocity through Version Numbers

Css Tricks - Mon, 04/29/2019 - 1:28pm

HTML5 and CSS3 were big. So big that they were buzzwords that actually meant something and were a massive success story in pushing web technology forward. JavaScript names their big releases now too: ES6, ES7, ES8... and it seems like it will keep going that way.

But HTML and CSS are done with that game. Shortly after the whole HTML5/CSS3 thing, the message was that there will be no HTML6/CSS4. There are reasons for that, like perhaps it's healthier for CSS modules to evolve independently of some global versioning number.

That said... as Dave says:

... the lull in excitement since those days is palpable....

People aren't equally excited about the big three languages of the web.

I’m on a bit of a quest to understand why these three technologies built to work together are so unequally yoked in popularity and their communities polarized from one another. One end of the spectrum experiences a boom while the other experiences a bust. The rising tide does not lift all boats.

Surely a major version number release for HTML and CSS could spark a ton of fresh enthusiasm.

I'll help. HTML6 could have HTML imports for web components, <include>, and a multi-select. CSS4 gets container queries, subgrid, standardized form control styling, and transitions to auto dimensions.

Direct Link to ArticlePermalink

The post Perceived Velocity through Version Numbers appeared first on CSS-Tricks.

Mobile App User Personas: Do They Hold Up In Reality?

Usability Geek - Mon, 04/29/2019 - 1:04pm
Mobile phones are at once intensely personal objects, representing our interconnectedness with others, and symbols of how far technology has entered into our natural daily lives, often replacing more...
Categories: Web Standards

Oh, the Many Ways to Make Triangular Breadcrumb Ribbons!

Css Tricks - Mon, 04/29/2019 - 4:39am

Oh, the Many Ways to Make Triangular Breadcrumb Ribbons

Let’s have a look at how we can create a row of links that sorta run into each other with a chevron-like shape and notch on each block like you might see in a hierarchical breadcrumb navigation.

You’ve probably seen this pattern a lot. It comes up often in things like multi-step forms and site breadcrumbs. For our purposes we’re going to call these “ribbons" so we know what we’re referring to as we go.

Like a lot of things on the web, we can make ribbons like these in many ways! I’ve created a demo page that brings a variety of them together, like using CSS triangles, SVG backgrounds, and the CSS clip-path property.

Starting with the HTML structure

For each demo, the HTML structure will largely be the same where we have a <nav> that acts as the parent element and then links inside it as the children.

<nav class="ribbon ribbon--modifier" role="navigation" aria-label="breadcrumbs"> <a class="ribbon__element" href="https://www.silvestar.codes/">Home</a> <a class="ribbon__element" href="https://www.silvestar.codes/categories/articles/">Blog</a> <a class="ribbon__element" href="https://www.silvestar.codes/articles/building-an-animated-sticky-header-with-custom-offset/" aria-current="page">Post</a> </nav>

Note that these elements should be accessible, according to A11y Style Guide website. It’s a good rule to build components with accessibility in mind and introducing accessibility at the very start is the best way to prevent the classic “I forgot to make it accessible" situation.

Let’s create some baseline styles

When it comes to things like this, we want to make sure the sizing of the elements is done right. For this purpose, we are going to define the font size of the .ribbon (that’s what we’re going to call these things) wrapper element and then use em units on the child element which are the links themselves.

/* Define font size of the wrapper element */ .ribbon { font-size: 15px; } /* Use ems to define the size of the ribbon element */ .ribbon__element { font-size: 1.5em; letter-spacing: 0.01em; line-height: 1.333em; padding: 0.667em 0.667em 0.667em 1.333em; }

This particular technique would be beneficial for defining the size of the triangle shape for each ribbon because we would use the same sizes to calculate triangle. And since we are using em units to calculate the ribbon element size, we could resize all elements by redefining the font-size on the wrapper element.

Let’s use CSS Grid for the layout because, well, we can. We could do this in a way that offers deeper browser support, but we’ll leave that up to you based on your support requirements.

We are going to define four columns:

  • Three for ribbon elements
  • One to fix spacing issues. As it is, the right arrow shape would be placed outside of the ribbon component and that could mess up the original layout.
/* The wrapper element * We're using CSS Grid, but ensure that meets your browser support requirements. * Assuming the use of autoprefixer for vendor prefixes and properties. */ .ribbon { display: grid; grid-gap: 1px; grid-template-columns: repeat(auto-fill, 1fr) 1em; /* Auto-fill the three ribbon elements plus one narrow column to fix the sizing issues */ }

If you prefer to avoid stretching the ribbon elements, the grid could be defined differently. For example, we could use max-content to adjust columns by content size. (Note, however, that max-content is not very well supported yet in some key browsers.)

/* Make ribbon columns adjust to the maximum content size */ .ribbon--auto { grid-template-columns: repeat(3, max-content) 1em; }

I am sure there are many different ways we could have gone about the layout. I like this one because it defines the exact gap between ribbon elements without complicated calculations.

Accessibility is not only adding aria attributes. It also includes color contrast and readability, as well as adding hover and focus states. If you don’t like outline style, you could use other CSS properties, like box-shadow, for example.

/* Use current link color, but add underline on hover */ .ribbon__element:hover, .ribbon__element:active { color: inherit; text-decoration: underline; } /* Clear default outline style and use inset box shadow for focus state */ .ribbon__element:focus { box-shadow: inset 0 -3px 0 0 #343435; outline: none; } Creating the unique triangular shape

We have more than one option when it comes down to defining the triangle at the end of each ribbon. We could:

  1. We could create a triangle using borders with pseudo-elements
  2. We could use an SVG background image on pseudo-elements
  3. We could use inline SVG images
  4. We could create a clip-path using the polygon() function

Let’s dig into each one.

Option 1: The border approach

First, we should set the element’s width and height to zero so it doesn’t get in the way of the pseudo-elements we’re using to draw the triangle with borders. Then we should draw the triangle using borders, specifically by defining a solid left border that matches the color of the background to make it blend in with the rest of the ribbon. From there, let’s define top and bottom borders and make them transparent. The trick here is to calculate the size of the border.

Our ribbon element has a content size of the line-height value plus the top and bottom paddings:

0.333em + 0.667em + 0.667em = 2.667em

That means our top and bottom borders should be half that size. The only thing left to do is to position elements absolutely to the correct side of the component.

/* The left arrow */ .ribbon--alpha .ribbon__element:before { /* Make the content size zero */ content: ''; height: 0; width: 0; /* Use borders to make the pseudo element fit the ribbon size */ border-bottom: 1.333em solid transparent; border-left: 0.667em solid #fff; border-top: 1.333em solid transparent; /* Position the element absolutely on the left side of the ribbon element */ position: absolute; top: 0; bottom: 0; left: 0; } /* The right arrow */ .ribbon--alpha .ribbon__element:after { /* Make the content size zero */ content: ''; height: 0; width: 0; /* Use borders to make the pseudo-element fit the ribbon size */ border-bottom: 1.333em solid transparent; border-left: 0.667em solid; border-top: 1.333em solid transparent; /* Position the element absolutely on the right side of the ribbon element and push it outside */ position: absolute; top: 0; right: 0; bottom: 0; -webkit-transform: translateX(0.667em); transform: translateX(0.667em); }

Since the right triangle should match the background color of the ribbon, let’s remember to add the correct border color for each ribbon’s pseudo-element.

/* The right arrow of the first element */ .ribbon--alpha .ribbon__element:nth-child(1):after { border-left-color: #11d295; } /* The right arrow of the second element */ .ribbon--alpha .ribbon__element:nth-child(2):after { border-left-color: #ef3675; } /* The right arrow of the third element */ .ribbon--alpha .ribbon__element:nth-child(3):after { border-left-color: #4cd4e9; }

And there we go!

See the Pen
CSS Grid Ribbon - Alpha
by Silvestar Bistrovi? (@CiTA)
on CodePen.

Option 2: The background image approach

We can also create a triangle using a background image. This requires creating an image that matches the design, which is a little cumbersome, but still totally possible. We are going to use SVG here since it’s smooth at any resolution.

Unlike the border triangle approach, we want to match the height of our pseudo-element with the height of the ribbon element, or 100%. The width of the component should match the left border width of the border triangle, which is 0.666666em in our case. Then we should use a white triangle for the background image on the triangle of the left side, and then use triangle images with color for the triangles on the right side. Again, we are using absolute positioning to place our triangles to the correct side of the ribbon element.

/* The left arrow */ .ribbon--beta .ribbon__element:before { /* Define the arrow size */ content: ''; height: 100%; width: 0.666666em; /* Define the background image that matches the background color */ background-image: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjQwIiB2aWV3Qm94PSIwIDAgMTAgNDAiIHdpZHRoPSIxMCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBmaWxsPSIjZmZmIj48cGF0aCBkPSJtNSAxNSAyMCAxMGgtNDB6IiBmaWxsLXJ1bGU9ImV2ZW5vZGQiIHRyYW5zZm9ybT0ibWF0cml4KDAgLTEgLTEgMCAyNSAyNSkiLz48L3N2Zz4=); background-position: center left; background-repeat: no-repeat; background-size: 100%; /* Position the element absolutely on the left side of the ribbon element */ position: absolute; bottom: 0; top: 0; left: 0; } /* The right arrow */ .ribbon--beta .ribbon__element:after { /* Define the arrow size */ content: ''; height: 100%; width: 0.667em; /* Define the background image attributes */ background-position: center left; background-repeat: no-repeat; background-size: 100%; /* Position the element absolutely on the right side of the ribbon element and push it outside */ position: absolute; top: 0; right: 0; bottom: 0; -webkit-transform: translateX(0.667em); transform: translateX(0.667em); } /* Define the background image that matches the background color of the first element */ .ribbon--beta .ribbon__element:nth-child(1):after { background-image: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjQwIiB2aWV3Qm94PSIwIDAgMTAgNDAiIHdpZHRoPSIxMCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBkPSJtNSAxNSAyMCAxMGgtNDB6IiBmaWxsPSIjMTFkMjk1IiBmaWxsLXJ1bGU9ImV2ZW5vZGQiIHRyYW5zZm9ybT0ibWF0cml4KDAgLTEgLTEgMCAyNSAyNSkiLz48L3N2Zz4=); } /* Define the background image that matches the background color of the second element */ .ribbon--beta .ribbon__element:nth-child(2):after { background-image: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjQwIiB2aWV3Qm94PSIwIDAgMTAgNDAiIHdpZHRoPSIxMCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBkPSJtNSAxNSAyMCAxMGgtNDB6IiBmaWxsPSIjZWYzNjc1IiBmaWxsLXJ1bGU9ImV2ZW5vZGQiIHRyYW5zZm9ybT0ibWF0cml4KDAgLTEgLTEgMCAyNSAyNSkiLz48L3N2Zz4=); } /* Define the background image that matches the background color of the third element */ .ribbon--beta .ribbon__element:nth-child(3):after { background-image: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjQwIiB2aWV3Qm94PSIwIDAgMTAgNDAiIHdpZHRoPSIxMCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBkPSJtNSAxNSAyMCAxMGgtNDB6IiBmaWxsPSIjNGNkNGU5IiBmaWxsLXJ1bGU9ImV2ZW5vZGQiIHRyYW5zZm9ybT0ibWF0cml4KDAgLTEgLTEgMCAyNSAyNSkiLz48L3N2Zz4=); }

There we go!

See the Pen
CSS Grid Ribbon - Beta
by Silvestar Bistrovi? (@CiTA)
on CodePen.

Option 3: The inline SVG approach

Instead of loading a different SVG triangle for each background image, we could use inline SVG directly in the HTML.

This particular approach allows us to control the fill color of each SVG arrow with CSS. The arrow size is calculated by the ribbon size. Once again, we are using the em units to define the size and arrows are absolutely positioned, like the other approaches we’ve seen so far.

/* Position arrows absolutely and set the correct size */ .ribbon--gamma .ribbon__element svg { height: 2.667em; position: absolute; top: 0; width: 0.667em; } /* The left arrow */ .ribbon--gamma .ribbon__element svg:first-child { fill: #fff; /* Define the background image that matches the background color */ left: 0; /* Stick left arrows to the left side of the ribbon element */ } /* The right arrow */ .ribbon--gamma .ribbon__element svg:last-child { left: 100%; /* Push right arrows outside of the ribbon element */ } /* Define the fill color that matches the background color of the first element */ .ribbon--gamma .ribbon__element:nth-child(1) svg:last-child { fill: #11d295; } /* Define the fill color that matches the background color of the second element */ .ribbon--gamma .ribbon__element:nth-child(2) svg:last-child { fill: #ef3675; } /* Define the fill color that matches the background color of the third element */ .ribbon--gamma .ribbon__element:nth-child(3) svg:last-child { fill: #4cd4e9; }

See the Pen
CSS Grid Ribbon - Gamma
by Silvestar Bistrovi? (@CiTA)
on CodePen.

Option 4: The clip-path approach

We can create the ribbon triangles with a polygon that masks the background. Firefox’s Shape Editor is a fantastic tool to draw shapes directly in the browser with a GUI, as is Clippy.

Since polygons must be created using percentages, we should use our best judgment to match the size of border triangles. Also, note that percentage-based polygons might look a little funny on some viewports, especially when element sizes are adapting to its surroundings, like wrapper elements. Consider redefining polygons for different viewports.

.ribbon--delta .ribbon__element { clip-path: polygon(95% 0, 100% 50%, 95% 100%, 0% 100%, 5% 50%, 0% 0%); }

Since we defined our wrapper element using CSS Grid, we should expand the ribbon elements but leave the last one at the size of the polygon triangle, which is 5% in our case. The last ribbon element should be wider by the size of the border triangle width to match the first two examples.

/* Make all ribbon elements (except the last one) wider by the size of the polygon triangle */ .ribbon--delta .ribbon__element:not(:last-child) { width: 105%; } /* Make the last ribbon element wider by the size of the border triangle */ .ribbon--delta .ribbon__element:last-child { width: calc(100% + .667em); }

See the Pen
CSS Grid Ribbon - Delta
by Silvestar Bistrovi? (@CiTA)
on CodePen.

Variations on these options

Now that we’ve learned how to create the breadcrumb ribbon a few different ways, we could play around with it, like adding shadows or gradients and different sizes.

Adding a shadow

We could add the shadow on our ribbon elements. Make sure to avoid the shadow on the left or right side of the ribbon element.

/* Add shadow under each ribbon element */ .ribbon--shadow .ribbon__element { box-shadow: 1px 3px 3px -3px black; }

See the Pen
CSS Grid Ribbon - Shadow
by Silvestar Bistrovi? (@CiTA)
on CodePen.

Using gradients for color

We could add gradients to our ribbon element. Be sure to match the color of the right triangle when doing so. Also, make sure to comply with contrast accessibility.

For example, if we are going to use the border approach or background image approach, we should use mostly horizontal (i.e. left-to-right) gradients (with the exceptions of some carefully calculated angled gradients). If we are using the clip-path approach, we could use any gradient version we wish.

/* Add gradient to the first ribbon element */ .ribbon--gradient .ribbon__element:nth-child(1) { background-image: linear-gradient(to right, #11ced2, #11d295); } /* Add gradient to the second ribbon element */ .ribbon--gradient .ribbon__element:nth-child(2) { background-image: linear-gradient(to right, #ef36b2, #ef3675); } /* Add gradient to the third ribbon element */ .ribbon--gradient .ribbon__element:nth-child(3) { background-image: linear-gradient(to right, #4c9fe9, #4cd4e9); }

See the Pen
CSS Grid Ribbon - Gradient
by Silvestar Bistrovi? (@CiTA)
on CodePen.

Working with size variations

Since the size of our ribbon elements depends on the font size of the wrapper element, defining different sizes is pretty straightforward.

/* Small ribbons */ .ribbon--small { font-size: 10px; } /* Big ribbons */ .ribbon--big { font-size: 20px; }

Here we go with a smaller set of ribbons:

See the Pen
CSS Grid Ribbon - Small
by Silvestar Bistrovi? (@CiTA)
on CodePen.

And here’s a nice set of chunky ribbons:

See the Pen
CSS Grid Ribbon - Big
by Silvestar Bistrovi? (@CiTA)
on CodePen.

Combining all the things!

We can also combine different modifier classes to achieve an even more styling. For example, let’s use gradient and shadow modifiers together:

See the Pen
CSS Grid Ribbon - Shadow Gradient
by Silvestar Bistrovi? (@CiTA)
on CodePen.

Any other angles to consider?

Making custom elements using different CSS techniques is a great way how each one of us could improve or refresh our knowledge. Before starting, it’s worth investing some thought into the maintainability and modularity of the component being built. A consistent naming convention, like BEM, is certainly helpful that. Accessibility is also a big deal, so starting with it in mind and documenting accessibility features along the way will serve you well.

We looked at four different approaches for drawing ribbon triangles. Have you used a different approach or know of one we haven’t considered here? Let me know in the comments!

The post Oh, the Many Ways to Make Triangular Breadcrumb Ribbons! appeared first on CSS-Tricks.

Interviewing for a Technical Position Doesn’t Have to Be Scary

Css Tricks - Fri, 04/26/2019 - 4:35am

Jacob Schatz (@jakecodes) is a staff engineer over at GitLab and was kind enough to share how he conducts job interviews for technical positions and his thinking process for them. Technical interviews are talked about often and can be a touchy subject for some, so it’s worth noting that this article expresses Jacob’s own opinions and are not necessarily shared by his employer.

Are you an interviewee who is terrified, exhausted, sad, or disappointed? I'd love to change that stigma.

I believe that people can have a great interview experience, and that I can simultaneously find the right candidate. Both things can happen at the same time! After your interview process is over, in a perfect world, regardless of outcome, you should feel good about yourself and the process. You might feel sad that you didn't get the job or excited to start your new job, but you should understand why in either situation.

At GitLab, I was put in charge of hiring very early on, and as such, I've seen thousands of resumes. When I first joined, I was asked to hire and form a team of front-end developers. I was employee #29 (we now have 500+), and I was the first front-end developer, so there was no hiring process for our team. We gradually created a process.

This article is aimed at both the interviewee, and interviewer. For the interviewee, I want you to know what a perfect interview can be like. Interviewing should not be scary or intimidating. This is a guide you can follow to do your part in creating the perfect interview. If you are an interviewer, maybe you have perfected your process. This is my view on how interviews can go in a perfect world. There are all different types of interviews, and this article focuses on interviewing developers of all experience levels. Over the years, I’ve latched on to some great processes, and this article is a behind-the-scenes look at that process for both sides of the candidacy.

Before I begin, it's important to remember that everyone is human and humans are not perfect. There are no perfect developers. Treat everyone like a regular human being. It's OK to be amazed at what some people are doing, but not OK to worship others. Talent is both congenital and acquired and you can acquire it too. Your interviewer and you are both imperfect. Interviews should not be focused around perfection. Here's what interviews should be.

Five things I look for in a candidate

The GitLab Values cover a lot of great points and you should read it. This is loosely based on those.

As an interviewer, I can only focus on so many things at once while being a productive, active listener. But I do have five specific things I am try to focus on:

  1. Does this person have a "good head on their shoulders"?
  2. Is this person technically where they need to be for this role?
  3. Is this person going to be self sufficient in this role?
  4. Does this person communicate well and will they communicate well with the team?
  5. Does this person handle positive and negative feedback well?

There are other things I'm looking for, of course, but these five things are enough to get you the job you want if you’re interviewing with me.

Forget nervousness. I won't ever hold it against you. I know you may be nervous, and that's totally fine. There is the rare occasion that nervousness becomes a debilitating factor, and in those cases, I just ask that you reschedule. Just don't hang up on me!

Recognize there's going to be bias

We have training on bias at GitLab. One thing I learned from the training is that everyone is biased, whether or not you think you are. At one point, I had the idea of doing blind interviews like they do for some orchestras. We never implemented it (and it would be tough) but that's why I keep a list of questions and a summary of what I want to cover in each interview. Each interview has a script I can follow. Everything is as repeatable and similar as possible. As the interview progresses, I'll be able to tell if I can hit the harder questions. Harder questions are not there to disqualify people, but to qualify people. If you get to my hard questions it means you have a ton of experience and knowledge under your belt. It's really important to know that I must ask trivia questions in some form but I don't qualify candidates based on trivia questions. It's about figuring the depth of your JavaScript knowledge and programming in general.

That being said, there is still one trivia question no one has ever gotten right. I'll just keep asking it, and I am sure some day, someone will get it. Trivia questions are fun, because I am a major JavaScript dork. I just love talking about all the ins and outs of JavaScript. I am looking for people that can be my coding buddy. Hiring people is about finding other people you can work with, not people that will work for you.

Inexperienced interviewers tend to test you on what THEY know (so they can feel a little more secure when they can ding you on an "wrong" answer).

In contrast, great interviewers focus on what YOU know, and facilitating a two-way conversation to explore a mutual fit.

— Jennifer Kim (@jenistyping) April 8, 2019

I want to know you're technically sound

This may be people's worst fear. The part of the interview where we ask questions like, "Why are manholes round?" The truth is that some companies may ask the medium-to-hard questions from LeetCode, and some may never ask any technical questions.

What I'm looking for in your skillset

Experience speaks louder than any technical interview question I can ask. For example, if I'm hiring for a front-end engineering role and someone tells me they built their own cool things that we can talk about, then that's awesome. I still may need to throw some more questions their way after that, or maybe the demo answers all my questions (though unlikely, but possible). But if we can walk through the code of something that you are super proud of, that’s great.

It’s helpful if you can tell me about something that you built for another company where I can see your code, or you can explain it sufficiently enough. What were the challenges? How did you deal with 10,000 comments? How did you deal with mobile? What were some challenges? I'll give you an example: You built the comment system for GitLab. For the comment system, an interesting challenge was dealing with loading users for the @ drop-down to mentioning other users. It turns out that the JSON payload for that drop-down can get quite large and loading it on page load makes the page load significantly slower. But loading that data on the first @ keypress is also slow because the payload can be more than 10 MB. We want the user to have a seamless experience and not realize the data needs time to load. So, a good way to talk about that experience would be to describe some of the approaches you considered, like:

  1. Load the data when the comment box first appears in the viewport.
  2. Load the data on the user's first mouseover of the textarea.
  3. Load the data once the user starts scrolling with enough momentum.

That last one isn't a boring solution, but is something I've heard someone say in an interview.

I might ask about algorithms and data structures

Hey interviewers, are you hiring someone for your marketing site? Don't ask them the hardest algorithms and data structure questions. Yes, algorithms and data structures play a huge part in everything, but it's more important that the candidate knows about responsive design, and maybe animations, and performance. Since we are talking about performance, they should know about Big O notation. They should know what causes re-paints. Look at Firefox Monitor and compare it to Salesforce. Everything about the Firefox site is much more snappy. Why is it more snappy? Why is the Salesforce site so chunky and slow? Resize them... oy vey! Big O would probably help you explain some parts, but being able to explain the whole picture is important.

Quick aside on Big O notation since I brought it up.

Big O is a way of describing the time your code will run in and/or the memory space your code will take up in a worst case scenario. I think it's really great to learn, and helps out in every day programming. You can and should learn it, which might take about an hour. After one hour, done or not, you’ll more than likely be prepared for any legitimate Big O question that interviewers would ask.

Big O is not something you need to take a course on. Here are some articles that can explain it to you in under an hour:

OK, back to algorithms and data structures in interviews.

Since there's a chance these types of questions will come up, it's worth doing a little homework in advance. There are two typical gold standards when studying for interviews that ask about algorithms and data structures.

There are many other things that are recommended for algorithm and data structure, heavy coding interviews, but rather than memorizing every example in the world (which won't solve any problems for you), it's better to learn how to solve these problems.

As I said above, front-end engineers should learn Big O for their health, because it's good for you, like eating your Wheaties. Interviewers should not ask extensive algorithms and data structure questions unless the job requires extensive knowledge of them. If I was designing a front-end framework, say like Vue, it would be important to optimize a DOM diffing algorithm or at least understand the implementation of the algorithm you are using. But does that mean I would ask seven extra hard questions from a CTCI? No. You are testing for understanding, not for memorization. When people work through these questions (when I ask them), I want to see that they thought through the problem and we worked it out together more than I want to see that they got the right answer. It's all about figuring out what you will be able to do, as an engineer, when you get the job — not what you memorized yesterday. A person who has knowledge of algorithms is going to be better at implementing them than someone who has to learn them on the job.

Are you hiring someone to build a dependency management system? This person needs to know a lot about algorithms and data structures.

These are two extreme ends of the spectrum, but in my opinion, not everyone needs to know how to write a red-black tree from scratch — but everyone should understand Big O. However, it will dramatically improve your skills as a software developer to learn typical algorithms and data structures.

When I do ask algorithm and data structure questions here are a few I do ask:

  • What is a linked list and can you show me how to implement one with and without an array in JavaScript?
  • What is the difference between BFS and DFS and can you implement one of them?

Getting these wrong will not disqualify anyone. Remember, I don't use trivia to qualify people.

Do you have a good head on your shoulders?

There are a lot of soft skills I'm looking for as well during the interview. It's my way of determining whether you have a "good head on your shoulders."

Pedantically speaking, that means you make good decisions, but it's much more than that to me. People who have a good head on their shoulders make sound decisions. It's good to have different opinions than me, but there is a standard of knowledge we should agree on. For example, we should all agree that laying out an entire blog with only absolute positioning is a bad idea. That is not a sound decision.

But I might create a scenario like this to check on those skills:

Let's go into CodePen and create a static blog homepage. We'll need a navigation menu, and we'll need a place for the title and article, and then at the bottom let's have some comments and a footer.

I'd then talk you through different ways you could create the navigation and the pros and cons to each. For a lot of the front-end developers I hire, I'd like to know that they know some core JavaScript so I might ask them add some small functionality using only vanilla JavaScript.

When a framework does everything for you, you don't need to do things yourself. I want to know that you get the whole picture.

A “good head on you shoulders" is a fancy way of telling me that you have your crap together. This is not an exhaustive list, but are the types of things that catch my attention:

  • You take care of yourself
  • You speak professionally (this has more of an impact than most people know)
    • Leave out super personal details
    • Answer questions succinctly
    • Take time to think
    • Say, "I don't know," when you don't know
    • Be confident, but not cocky, even if you aren't
  • You finish what you start
  • You are honest
  • You are able to say no
  • You know what you want and you want to help others get what they want
  • You'll disagree and even debate, but know when to let something go
  • You are able to effectively communicate in an interview
    • Is this conversation easy or exhausting?
    • Are you fluent in English? Accents are totally OK!
    • Do you grasp the concepts being discussed?
  • You’re a kind person.

On that last point: kindness doesn't mean you are a pushover. Kindness is a major part of challenging others and giving feedback.

I want to see that you are self-sufficient

It seems obvious now, but I am convinced — after working at GitLab — that self-sufficiency is what interviewers should seek in everyone being hired. Self-sufficiency plays a big part in your role in the company.

For example, to go extreme, think about a GM, who may have the least amount of external direction of anyone on a team. Everyone has responsibilities, but a GM must often be good at many things, including (but not limited to) marketing, sales, and management. All this changes based on the size of the team. Their role may be the most vague. They are very self-sufficient. A senior developer (in my opinion) should be able to take on an entire large piece of functionality and implement it properly.

This is not to say a developer shouldn't communicate during the process. They should ask questions, and pair with other people to find the best way forward.

Reviewing an interviewee’s code has the opportunity to be boring (in a good way) as we know what to expect from them. We are relying on them to mentor less experienced developers. Junior developers should be self sufficient too, but probably won't take on large initiatives alone. Junior developers often work great in small chunks. For example, it might be a great thing for a junior developer to take on the smaller tasks that a senior developer has on a larger project. Senior developers can also mentor junior developers and nudge them in the right direction to help them become more self-sufficient, which is a great thing for both parties — and also a great thing for the manager, as they can delegate more work to a senior developer.

If you are a front-end developer and need hand-holding at this point in your career, that is totally 100% OK, and everyone has been there. Or, if you are applying to a lot of places and not getting anywhere, and are extremely frustrated: I suggest that you become a little more self-sufficient before you apply. One way I suggest to become more self-sufficient and nab that job you want: Forget code examples, little shopping cart apps, and their ilk, as they don't fair well for job interviews. Build something full-fledged for someone and do it for cheap or free. Find a church, synagogue, homeless shelter or someone near you and offer to make them a website.

Just remember that free clients are often the worst clients. It will be worth it when you can say that you've done work for a few clients. For bonus points, document your work in a few blog posts. This stuff looks great on resumes and will make you stick out from the rest. I know that anyone can get an easy website through Wix or other site building platforms, but there's nothing like a wonderful custom-designed website. I think I made around 10 or so websites before I had my first programming job. I could fill a book with crazy stories from those times.

Communication and feedback is key

This is another point that seems obvious, but is hard to do right. Communication is well documented in the GitLab Handbook so I won't cover it, except to say that I follow GitLab's values and we are looking for others who desire to follow those values as well. Positive and negative feedback is also well documented in the GitLab Handbooks, so I won't cover it here.

How I go about the rest of the interview

Because we interview a lot of candidates at GitLab, we follow a common flow so we can repeat it easily. I won't go into specifics about our interview process, because it's constantly evolving. But, in general, this is the flow I follow.

Tell me about yourself

You'll get asked the famous question that goes along the lines of "tell me about yourself," "tell me what you've been doing," or "tell me about your time at [Company Name]." When I ask this question, I am trying to find the connection between the job you applied for and the jobs you've had in the past. It's good to find the common ground ahead of time.

Like, for example, as an employee of GitLab, if I were personally applying to a FAANG as a front-end engineer, I am sure both GitLab and that company are trying to get page load times to be faster. Maybe I noticed there were 26K event listeners on a page when I first joined GitLab and was able to reduce it down to 0, decrease the loading time by 50%, down to a speed of 200ms. I am sure this would be something relevant to the conversation.

So, as an interviewee, I might say something like this:

"Hi! I am a front-end engineer at GitLab, I've been here for 3.5 years and during my tenure I've made a ton of huge improvements, some of the areas I loved working on are performance, UX design implementation, and architectural design.

You don't want to get into tons of details at this point, but it's good to give the interviewer some facts to work with. It is frustrating when I ask this question and someone goes into a 10-minute detailed account of their entire career.

What made you apply to our company?

The interviewer might ask, "What made you decide to apply to our company?" Hopefully, you are excited to work at this company — otherwise, why bother applying for it?

For some reason or another, this question often sends a candidate into overdrive and they wind up mixing up the name our company. That's perfectly normal behavior, especially if your company sounds like another company.

What I'm looking for at this point is to see whether you are just looking for a job or that you’re really excited to work with us. We want people who really want to work with us. This is when I can also see if a person knows anything about our company. For example, some people like our values, have read them and want to work at a company with these values. Some people want to solve big problems like the ones we are tackling. Some people have seen talks and read articles from our team and would love to work around smart people like them.

What are your five things?

Lastly, I like to ask if a candidate has any questions for me. This is an important part of the interview, and you should extensively think this through beforehand. Your goal is to make me respond with: “Oooohhh, great question!" On one hand, I am truly trying to answer any questions you have, so don’t be shy. On the other hand, I am also trying to gauge your interest in the job, so something like, “Uh, I dunno," is usually a big bummer to hear because it signals that maybe you’ve tuned out, or the job is not interesting to you. that’s can leave an undesirable aftertaste.

Look up your interviewers and find out about them. Doing this in advance can be an eye-opening exercise. You might find out about their customer acquisition strategy which could lead to a ton of other interesting questions. If the company is a startup, do they plan on being acquired, or do they want to IPO? When you have a clear, well-thought question, it makes you sound professional, which again, is one of the things I listed as important.

If you can’t think of any questions to ask, then do you really want this job in the first place? If the interviewer has a personal website, go check it out, and if nothing else, you can ask them about the comic book they wrote and posted to their website.

But I’d advise:

  1. Ask the interview questions that you are generally interested about. Think about this before the interview because a really thoughtful question generally improves your candidacy quite a bit.
  2. What are you, the candidate, looking for in a company? What does this person, the interviewer, need to prove to you in order for you to take this job?
  3. Do these people have a good head on their shoulders like you do? It works both ways, you know.
  4. Does this look like a fun job? Do you even want a fun job?
  5. Who would you report to? Did you talk to them? Will you get a chance to during the interview process?
  6. Are you underrepresented? Like, are you replacing someone or filling a new role? How many others will be doing what you’re doing? What signs should other underrepresented people look out for? What signs would show you that this is a good environment for you?

Don't ask about money or benefits at this point; those things can (and likely should) be covered with a recruiter introduction call before you get to a person like me.

Conclusion

Interviewing, unlike programming, is not an exact science. You’re trying to prove that you are excited about the prospect of working with a company. You want to prove this to the interviewer and yourself. Hopefully, you want a job that is interesting. This guide isn’t a script to follow, but more of a few loose ideas to help you get into the mindset of the interviewer, with a few tips for other interviewers strung in there as well. Maybe I pointed out things you might not have known before.

Just remember that, in theory, interviewing should not be a scary process, but more of a find-some-buddies-to-work-with process.

The post Interviewing for a Technical Position Doesn’t Have to Be Scary appeared first on CSS-Tricks.

Corvid by Wix: Accelerated Development of Web Applications

Css Tricks - Thu, 04/25/2019 - 10:16am

(This is a sponsored post.)

It's been interesting to watch Wix evolve from a website builder into a full-fledged platform for developing web applications. It's still just as easy for anyone to spin up a website with the visual builder that's always been there, but Wix Code was introduced a little while back as a way to give developers more hands-on control of the code under the hood to make custom sites.

Well, that evolution continues as Wix Code recently became Corvid by Wix.

Why the name change? It's totally understandable when you see just how many new features and tools are available for developers. There are literally 28 features in all, from a payment API and custom forms to CRM functionality and a Node.js server for writing JavaScript for both the front and back end. There's a ton of control and power and it's certainly worth checking out.

But what we really want to spotlight here are the brand-new features the Wix team rolled out along with the name change earlier this month.

Connect to External Data Sources

Wix has provided a built-in database for a while, but now Corvid works with external data. That means you get even more control over the data on a Wix site and moer opportunities to fetch and optimize data. We've talked about the numerous ways to use spreadsheets as data sources before. Now, that same concept can be brought into the Wix ecosystem!

Testing and Deploying Changes

Want to see if changing the color of a button from green to purple increases conversion? Or maybe you're trying to decide between two new page layouts and aren't sure which one will work best? Corvid lets you have it both ways with a feature to create a release candidate and serve it to a percentage of visitors before rolling it out to everyone. It's native A/B testing, which is a powerful marketing technique, not to mention a solid way to test user experience.

Local Development

The front-end visual editor in Wix makes building and editing sites an easy experience. It's especially great for those who don't work with code often or even at all.

But many CSS-Tricks readers like yourself enjoy working with code and are good at it. Corvid brings a built-in IDE to the table. Or, if you prefer, pull your Wix project files into your local environment and use the code editor of your choice.

So, whether you're more comfortable working with a visual interface, a built-in editor, or locally, Corvid has got you covered.

App Monitoring

Need access to console logs, HTTP functions, and web module functions? Yep, Corvid offers all of that, too. The system continually monitors Wix sites and logs activity all the while so you know when an error takes place and what caused it. Those of you who have worked with monitoring services before know how great it is to have error logs for quickly finding and fixing the source of an issue — and now it's built right into Wix.

Speaking of working with monitoring services, Corvid will integrate with those as well so you never have to interrupt things or make a switch if you don't want to. So nice!

Start Playing with Corvid!

What we've covered here is merely the tip of the iceberg when it comes to Corvid and all that it offers for a complete development platform and framework. Plus, there's so much more to come, so definitely keep an eye out for new updates and releases as they're announced... which we've seen moves at a fast pace.

Meet Corvid

Direct Link to ArticlePermalink

The post Corvid by Wix: Accelerated Development of Web Applications appeared first on CSS-Tricks.

Using Parcel as a Bundler for React Applications

Css Tricks - Thu, 04/25/2019 - 4:22am

You may already be familiar with webpack for asset management on projects. However, there’s another cool tool out there called Parcel, which is comparable to webpack in that it helps with hassle-free asset bundling. Where Parcel really shines is that it requires zero configuration to get up and running, where other bundlers often require writing a ton code just to get started. Plus, Parcel is super fast when it runs because it utilizes multicore processing where others work off of complex and heavy transforms.

So, in a nutshell, we’re looking at a number of features and benefits:

  • Code splitting using dynamic imports
  • Assets handling for any type of file, but of course for HTML, CSS and JavaScript
  • Hot Module Replacement to update elements without a page refresh during development
  • Mistakes in the code are highlighted when they are logged, making them easy to locate and correct
  • Environment variables to easily distinguish between local and production development
  • A "Production Mode" that speeds up the build by preventing unnecessary build steps

Hopefully, you’re starting to see good reasons for using Parcel. That’s not to say it should be used 100% or all the time but rather that there are good cases where it makes a lot of sense.

In this article, we’re going to see how to set up a React project using Parcel. While we’re at it, we’ll also check out an alternative for Create React App that we can use with Parcel to develop React applications. The goal here is see that there are other ways out there to work in React, using Parcel as an example.

Setting up a new project

OK, the first thing we need is a project folder to work locally. We can make a new folder and navigate to it directly from the command line:

mkdir csstricks-react-parcel && $_

Next, let’s get our obligatory package.json file in there. We can either make use of npm or Yarn by running one of the following:

## Using npm npm init -y ## Using Yarn, which we'll continue with throughout the article yarn init -y

This gives us a package.json file in our project folder containing the default configurations we need to work locally. Speaking of which, the parcel package can be installed globally, but for this tutorial, we’ll install it locally as a dev dependency.

We need Babel when working in React, so let’s get that going:

yarn add parcel-bundler babel-preset-env babel-preset-react --dev

Next, we install React and ReactDOM...

yarn add react react-dom

...then create a babel.rc file and add this to it:

{ "presets": ["env", "react"] }

Next, we create our base App component in a new index.js file. Here’s a quick one that simply returns a "Hello" heading:

import React from 'react' import ReactDOM from 'react-dom' class App extends React.Component { render() { return ( <React.Fragment> <h2>Hello!</h2> </React.Fragment> ) } } const rootElement = document.getElementById("root"); ReactDOM.render(<App />, rootElement);

We’ll need an HTML file where the App component will be mounted, so let’s create an index.html file inside the src directory. Again, here’s a pretty simple shell to work off of:

<html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Parcel React Example</title> </head> <body> <div id="root"></div> <script src="./index.js"></script> </body> </html>

We will make use of the Parcel package we installed earlier. For that to work, we need to edit the start script in package.json file so it looks like this:

"scripts": { "start": "NODE_ENV=development parcel src/index.html --open" }

Finally, let’s go back to the command line and run yarn start. The application should start and open up a fresh browser window pointing at http://localhost:1234/.

Working with styles

Parcel ships with PostCSS out of the box but, if we wanted to work with something else, we can totally do that. For example, we can install node-sass to use Sass on the project:

yarn add --dev node-sass autoprefixer

We already have autoprefixer since it’s a PostCSS plugin, so we can configure that in the postcss block of package.json:

// ... "postcss": { "modules": false, "plugins": { "autoprefixer": { "browsers": [">1%", "last 4 versions", "Firefox ESR", "not ie < 9"], "flexbox": "no-2009" } } } Setting up a production environment

We’re going to want to make sure our code and assets are compiled for production use, so let’s make sure we tell our build process where those will go. Again, in package-json:

"scripts": { "start": "NODE_ENV=development parcel src/index.html --open", "build": "NODE_ENV=production parcel build dist/index.html --public-url ./" }

Running the yarn run build will now build the application for production and output it in the dist folder. There are some additional options we can add to refine things a little further if we’d like:

  • --out-dir directory-name: This is for using another directory for the production files instead of the default dist directory.
  • --no-minify: Minification is enabled by default, but we can disable with this command.
  • --no-cache: This allows us to disable filesystem cache.
&#x1f4a9; CRAP (Create React App Parcel)

Create React App Parcel (CRAP) is a package built by Shawn Swyz Wang to help quickly set up React applications for Parcel. According to the documentation, we can bootstrap any application by running this:

npx create-react-app-parcel my-app

That will create the files and directories we need to start working. Then, we can migrate over to the application folder and start the server.

cd my-app yarn start Parcel is all set up!

Parcel is worth exploring in your next React application. The fact that there's no required configuration and that the bundle time is super optimized makes Parcel worth considering on a future project. And, with more than 30,000 stars on GitHub, it looks like something that's getting some traction in the community.

Additional resources
  • Parcel Examples: Parcel examples using various tools and frameworks.
  • Awesome Parcel: A curated list of awesome Parcel resources, libraries, tools and boilerplates.

The source code for this tutorial is available on GitHub

The post Using Parcel as a Bundler for React Applications appeared first on CSS-Tricks.

Moving from Gulp to Parcel

Css Tricks - Thu, 04/25/2019 - 4:22am

Ben Frain just made some notes about the switch from Gulp to Parcel, a relatively new "web application bundler" which, from a quick look at things, is similar to webpack but without all the hassle of setting things up. One of the things I’ve always disliked about webpack is that you kinda have to teach it what CSS, HTML and JS are before making whatever modifications you want to those files. However, Parcel does a lot of the asset management and configuration stuff for us which is super neat — hence, Parcel claim that it requires “zero configuration.”

If you’d like to learn more about Parcel then there’s a great post by Indrek Lasn that details how to get started and even shows off a little bit about how Parcel is often faster than alternatives like webpack. We also just published a post by Kingsley Silas that explains how to use Parcel with React.

Direct Link to ArticlePermalink

The post Moving from Gulp to Parcel appeared first on CSS-Tricks.

That Time I Tried Browsing the Web Without CSS

Css Tricks - Wed, 04/24/2019 - 4:12am

CSS is what gives every website its design. Websites sure aren’t very fun and friendly without it! I’ve read about somebody going a week without JavaScript and how the experience resulted in websites that were faster, though certain aspects of them would not function as expected.

But CSS. Turning off CSS while browsing the web wouldn’t exactly make the web far less usable... right? Or, like JavaScript, would some features not work as expected? Out of curiosity, I decided to give it a whirl and rip the CSS flesh off the HTML skeleton while browsing a few sites.

Why, you might ask? Are there any non-masochistic reasons for turning off CSS? Heydon Pickering once tweeted that disabling CSS is a good way to check some accessibility standards:

  1. Common elements like headings, lists, and form controls are semantic and still look good.
  2. A visual hierarchy is still established with default styles.
  3. The content can still be read in a logical order.
  4. Images still exist as <img> tags rather than getting lost as CSS backgrounds.

A WebAIM survey from 2018 reported that 12.5% of users who rely on any sort of assisted technology browse the web with custom stylesheets, which can include doing away with every CSS declaration across a site. And, if we’re talking about slow internet connections, ditching CSS could be one way to consume content faster. There’s also the chance that CSS is disabled for reasons outside our immediate control, like when a server has hiccups of fails to load assets.

As an experiment, I used five websites and a web app without CSS, and this post will cover my experiences. It wound up being a rather eye-opening adventure for me personally, but has also informed me professionally as a developer in ways I hope you’ll see as well.

But first, here’s how to disable CSS

You’re absolutely welcome to live vicariously through me in the form of this post. But for those of you who are feeling up to the task and want to experience a style-less web, here’s how to disable CSS in various browsers:

  • Chrome: There’s actually no setting in Chrome to disable CSS, so we have to resort to an extension, like disable-HTML.
  • Firefox: View > Page Style > No Style
  • Safari: Safari > Preferences... > Show Develop menu in menu bar. Then go to the Develop dropdown and select the “Disable Styles” option.
  • Opera: Like Chrome, we need an extension, and Web Developer fits the bill.
  • Internet Explorer 11: View > Style > No style

I couldn’t find a documented way to disable CSS in Edge, but we can remove CSS from it and any other browser programmatically via the CSS Object Model API in the DevTools console:

var d = document; for (var s in S = d.styleSheets) S[s].disabled = true; for (var i in I = d.querySelectorAll("[style]")) I[i].style = "";

The first loop disables all external and internal styles (in <link> and <style>), and the second eliminates any inline styles. The caveat here, however, is that elements can still dynamically be given new inline styles. To instantly erase them, the best workaround is adding a timer. Something like this:

(f = function(){ // Remove CSS ... setTimeout(f, 20); })();

Alternatively, there are text-only browsers — such as the ancient Lynx — but expect to be living without video, images (including SVGs), and JavaScript.

Through the style-less looking glass...

For each site I surfed without CSS — Amazon, DuckDuckGo, GitHub, Stack Overflow, Wikipedia and contrast checker called Hex Naw — I’ll share my first impressions and put some suggestions out there that might help with the experience.

Get ready, because things might get a bit... appalling. &#x1f631;

Website 1: Amazon.com The Amazon.com homepage with CSS (left) and without CSS (right).

There’s no real need for an introduction here. Not only is Amazon a household staple for so many of us, it also powers a huge chunk of the web, thanks to their ubiquitous Amazon Web Services platform.

There’s a vast number of things going on here, so I’ll explore the style-less stuff that gets in my path while finding a product and pretending to purchase it.

The Amazon.com results for a “mac mini” search query.

On the homepage, I immediately see a sprite sheet used by the site. It’s really in place of where the logo could be, thus making it tough to know whether or not those images are intended to be there. Each sprite contains multiple versions of the logo, and even if I could see the “Amazon” word mark in it, it’s surprisingly that it's not the global home link. If you’re curious where the home link really is, it’s this structure of spans where the logo is served up as background image... in CSS:

<a href="/ref=nav_logo" class="nav-logo-link" aria-label="Amazon" tabindex="6"> <span class="nav-sprite nav-logo-base"></span> <span class="nav-sprite nav-logo-ext"></span> <span class="nav-sprite nav-logo-locale"></span> </a>

The next problem that arises is that the “Skip to main content” link doesn’t look like a typical skip link, yet it works like one. It turns out to be an <a> element without an href, and JavaScript (yes, I did leave that enabled) is used to mimic anchor functionality.

When I start a search, I have to look further below the “Get started” link to see the suggestions. Under the “Your Lists” and “Your Account” items, it becomes difficult to tell the links apart. They appear all strung together as if they were one super long mega link. I believe it would have been more effective to use a semantic unordered list in this scenario to maintain a sense of hierarchy.

Under all those search suggestions, however, the account and navigation links are easier to read since they’re separated by some space.

Interestingly, the carousel lower down the page is still somewhat functional. If I click the “Previous page” or “Next page” options, the order of the images is changed. However, hopping between those options required me to scroll.

The carousel appears with its pages stack on top of another. The previous or next page shows up on top.

Skipping down a bit further, there’s an advertisement element. It contains an “Ad feedback” string that looks static just like what we saw with the “Skip to main content” link earlier. Well, I clicked it anyway and it revealed a form for sharing feedback on the advertisement relevance.

To make the call to action clearer, “Ad feedback” should be a link or button.

You may have missed it, but there’s a blank button above the two groups of form labels and the radios buttons are out of place. The structure is confusing because I don’t know which labels belong to which radio buttons. I mean, I guess I could assume that the first label goes with the first radio input, but that’s exactly what it is: a guess.

What’s also confusing is that there are Submit buttons between the “Close Window,” “Cancel,” and “Send Feedback” options at the bottom of the form. If I press any of these, I’m taken back to the ad. Now, suppose I were blind and using a screen reader to navigate this same part, even with the presence of CSS. I would be told “Submit, button” for two of the buttons and would therefore have zero clue what to do without guessing. It’s another good reminder about the importance of semantics when handling markup (button labels in this case) and being mindful of how much reliance is placed on JavaScript to override web defaults.

Doing a search — let’s say for “Mac Minis” — I can still access and understand the product ratings since they are displayed as text (instead of the tooltips they are otherwise) in place of stars. This is a good example of using a solid textual fallback when an image is used as visual content, but is served as a background image in CSS.

The page required me to scroll a while to get to the actual search results. Notice that ginormous overlay of a sponsored product.

Having chosen the Mac Mini with Intel Core i3, I’m greeted by other Mac products above the product I’ve selected and have to navigate beyond them to select the quantity I want to purchase.

The product page displays Amazon Prime membership info slapped between the quantity selection and purchase buttons.

Scroll down, and an “Add to Cart” button is displayed next to a label bearing the same content. That’s redundant and probably unnecessary since a <button> element is capable of holding its own label:

<button>Add to Cart</button>

Next up, we have an offer for an Amazon Prime membership. That’s all fine and dandy, but notice that it’s inserted between the product I’m purchasing and the “Buy Now” button. I have a really hard time knowing whether clicking “Buy Now” is going to add the Mac Mini to checkout, or whether I’m purchasing Amazon Prime instead.

I also wanted to play around a bit, so I tried removing the Mac Mini from my cart once I figured out how to add it. It took me like ten seconds to locate the cart so I could edit it. Turns out it was directly next to “Proceed to checkout (1 item)” link but rams right up alongside it so it all looks like a single link.

Overall, it wasn’t difficult to find a product. On the other hand, the path to checkout became more of a headache as I proceeded. There was some poor semantic- and accessibility-related practices that caused confusion, and important buttons and links became more difficult to find.

&#x1f44d; What the Site Does Well &#x1f4a1; What the Site Can Improve Carousels are functional even without styling. The logo relies on a background image, obscuring the path back home. The content hierarchy is still generally helpful for knowing where we are on a page. Many links and anchors rely on JavaScript and do not appear to be interactive. The order of elements remains roughly in tact. Links often bump up against each other or are placed outside where they would be relevant. Great use of fallbacks for product rating that rely on background images. Button labels are either misleading or repetitive. Form elements fail to align themselves properly. There’s a rough journey to check out. Website 2: DuckDuckGo The DuckDuckGo homepage with CSS (left) and without CSS (right).

Have you used DuckDuckGo before? I assume many folks reading CSS-Tricks have, but for those who may be hearing of it for the first time, it’s an alternative to Google search with an emphasis on user privacy.

So, getting started with this is a little misleading because the DuckDuckGo homepage is super simple. Not much can go wrong there, right? Well, it’s a little more involved than that since we’re dealing with search results, content hierarchy and relevance once we get into making search queries.

Right off the bat, what I’m greeted with is a lot more content than I would have expected for such a simple lander. At it’s not totally clear what website this is by scanning the website. The first mention of the product name is the fourth item in the first unordered list and it’s a call to action to “Spread DuckDuckGo.” The logo is totally missing, which obviously means it’s used as a background... in CSS.

Speaking of that unordered list, I assume what I’m seeing belongs in the header, and there’s no skip navigation. We have a triple arrow icon (is that a mobile menu or a menu to hide the least important items, or something else?), followed by privacy-related content, social media links, something that looks like one link but is actually two links for “About DuckDuckGo” and “Learn More.”

Finally, toward the very bottom is where the primary use case for the site actually comes up: the search bar. I assume the “S” label means “Search” and the “X” label is shorthand to clear the search field.

Alright, onto performing a search. It’s super cool that I can still see auto-suggestions and use the up and down arrow keys to highlight each one. Clearing the field though, the suggestions don’t disappear until after I refresh the page.

Performing a search and checking out the auto-suggestions.

Everything in the Settings menu are items in a list including what should be headings — “Settings,” “Privacy Essentials,” “Why Privacy,” “Who We Are,” and “Keep in Touch.” These are very likely part of a mobile men if CSS was enabled, perhaps triggered by that triple arrow link thing at the top. In that menu, I see four blank bullet points between “Settings” and “More Themes.”

The DuckDuckGo homepage exposed a few glaring usability issues right off the bat.

Coming here as a new user, I have no idea what those empty list items are, but the bullets I highlighted in the screenshot above are actually the theme buttons. To clarify the intent, some fallback text would be helpful, and these should be radio or normal buttons instead of list items (considering their functionality).

Every block of content with an “X” — including the “Settings” — cannot be dismissed; however, clicking the “X” above an image of a hiker image does cause a chunk of content to clear off the screen — thanks to JavaScript still being enabled. What I really find awkward is the redundant numeration in the ordered list under “Switch to DuckDuckGo...” We see this:

1. 1We don’t store your personal info 2. 2We don’t follow you around with ads 3. 3We don’t track you. Ever.

Looks like some mixed use case of semantic markup with some other way to display list item numbers.

The third “X” down has functionality.

There’s a colossal amount of white space under the hiker image until the first <h1> element. Assuming they’re either links or buttons, clicking every instance of “Add DuckDuckGo to [browser]” does nothing. Each section’s illustration causes some unnecessary horizontal scrolling, which is a common issue we’ll see in the other sites we look at.

Scrolling through white space between hiker image and first-level heading. Wheee!

After those sections, there’s a blank box and I have no idea what it is.

A blank box that appears to have no purpose.

I cracked open DevTools and it turns out to be a <body> element in an <iframe> that holds only JavaScript for something related to POST requests. It might as well be one of those elements we should leave alone.

Following that, I see two repeated instances of “Set as Default Search Engine” wrapped around a “Set as Homepage” section.

The instructions in Safari to set the search engine as your default or your homepage. Instructions may differ from one browser to another.

These must have been the instructions that popped up when I clicked the “Add DuckDuckGo...” actions, but it shows the impact hiding and showing content can have when we’re dealing with straight markup. Instead of repeating content, the corresponding links or buttons should point to one instance. That would cut the redundancy here.

OK, time to finally get into search. The first thing I see in the search results is an empty box with an instruction to ignore the box. Okey-dokey then.

DuckDuckGo wants me to ignore a box.

Moving on, did you see that DuckDuckGo link? That must be the logo, and I wonder why this was not on the homepage. Seems like low-hanging fruit for improvement.

The search bar still functions normally with the exception of the “S” and “X” buttons that have swapped places from where they were on the homepage.

Onto the search results. I could easily distinguish one result from another. What I found quite unnecessary, yet funny, is that the “Your browser indicates if you’ve visited this link” messaging that’s located at the end of each page title. That would be super annoying from a screen reading perspective. Imagine hearing that repeated at the end of every page title. That messaging is there to be displayed alongside checkmarks that contain tooltips that hold that messaging. But, with CSS disabled, well, no checkmarks and no tooltips. As a result, all I get is an extra long heading.

Search results on DuckDuckGo are still well structured with CSS disabled, but notice the messaging that is appended to each result title.

The navigation bar that is normally displayed as tabs to filter by different types of results (e.g. Images) seems to do nothing at this point because it’s hard to tell that they are filters without styling. But if I click on the Images filter, the image results are actually loaded lower down onto the page, piled right on top of the Web results, and the page becomes mega long as a result. Oh, and you might think that scrolling all the way back up (and it’s a long way up) then clicking another filter, say Videos, would replace the images, but that simply inserts video thumbnail images below the images making an already mega long page a super mega long page. Imagine the page weight of all those assets!

Well, you don’t have to. According to DevTools, images alone account for 831 requests and a total weight of 23.7 MB. Hefty!

The real kicker is that it’s not immediately clear that all those images have loaded visually.

The last couple of items are worth noting. Clicking the “Send feedback” link apparently does nothing. Maybe that triggered a modal with CSS? And, although the “All Regions” link does not resemble a link and I could’ve easily ignored it, I was curious enough to click it and was taken to an anchor point of a list of countries. The last two links just made their corresponding contents appear under the list country options.

The “All Regions” option is secretly acting as an anchor.

There’s a lot going on here and there are clearly opportunities for improvement. For example, there are calls to action that display as normal text that should be either be links or buttons instead. Also, we’d think the performance of a site would get better with CSS disabled, but all those loaded assets in the search results are prohibitive. That said, the search experience isn’t painful at all... that is, unless you’re digging into images or videos while doing it.

&#x1f44d; What the Site Does Well &#x1f4a1; What the Site Can Improve Search is consistent and works with or without CSS. A “skip” link for would help with keyboard browsing. The content hierarchy makes content easy to read and search results a clean experience. Non-link items in the “Settings” menu should be headings for separate unordered lists so there is a clear hierarchy for how the options are grouped. Good use of a homepage link at the top of the search results page. Some content is either duplicated or repeated because the site relies on conditionally showing and hiding content. Make sure that all calls to action render as links instead of plain text. Use a fallback solution to filter the types of search results to prevent items stacking and help control hefty page weight. Website 3: GitHub The GitHub homepage with CSS (left) and without CSS (right).

Hey, here’s a site many of us are well familiar with! Well, many of us are used to being logged into it all the time, but I’m going to surf it while logged out.

Already, there’s a skip link (yay). There’s also a mobile navigation icon that I expect will do nothing, and am proven right when I try.

That big gap of white? It’s an SVG icon with a white fill, according to DevTools.

Between some of the navigation items, there are unnecessarily giant gaps. If you click on these, they still function as dropdown menus. They are <details> and <summary> elements... but something feels semantically wrong. It is nice that the menu items are actually unordered list items and that native browser functionality can still take place by using a semantic way to expand content. But that SVG icon messes with me.

Before typing anything into the field, I see three instances of “Search All GitHub” and “Jump to” links. I have no idea which to click, but if I do a search, the keyword shows up in the third group.

There is no clear connection between the search input and the three groups of links.

Everything else on the homepage seems fine except for a number of overly large images horizontally overflowing the window.

Scrolling down to see large images overflowing the browser window.

Let’s go back to the search bar and navigate to any repo we can find. Right under the Search button, we have two nearly identical secondary navigation bars that return the repository counts, code, commits, and other meta. Without looking at the source, I have no clue what the purpose is for having two of these.

Search results for a “javascript tips” query.

Repository pages still have an easy-to-follow structure and a logical hierarchy for the most part. While logged out and having my cache cleared before coming, the "Dismiss" button for the “Join GitHub today” block still performs as I’d expect. Like we saw earlier on Amazon, the tag links are difficult to tell apart because they run together as a single line.

A repository page in a logged out state.

The next two buttons — “JavaScript” and “New Pull Request” — don’t seem to do anything when I click them. I’d imagine the pull request button should be disabled while viewing as a guest since, unless it’s intended to take a user to a log in screen first... but even that doesn’t feel right. Turns out that the button is indeed disabled when CSS is active, though. Then the rest of the page is fairly easy to understand.

If you’re here mainly for managing, contributing to, or checking out repositories, you won’t face a whole lot of friction since the hierarchy plays out well. You’ll experience pretty much the same elsewhere, whether you’re looking at pull requests, issues, or individual files. Most of the hurdles live in less prominent pages on the site.

&#x1f44d; What the Site Does Well &#x1f4a1; What the Site Can Improve The hierarchy and structure of many pages are really easy to follow and make logical sense. Use the height and width attributes on <img> elements and SVGs to prevent them from blowing up. Most of the SVG icons embedded on the page are appropriately sized. Watch for empty list items. Nice use of a skip link in the header. Ensure that button labels use full words. Make sure links have whitespace or line breaks between them to prevent run-ons. Website 4: Hex Naw The Hex Naw homepage with CSS (left) and without CSS (right).

This next site is an online tool I use often to check color contrasts for accessibility. And for a site that is so big on color, there’ s probably a lot happening here with CSS, so it should get interesting.

There’s immediately a large amount of space above the navigation and no skip links. The hamburger and close buttons for the mobile layout and “X” buttons next to each color to test are oversized.

We’re missing skip links and there is excessive space above the navigation.

Oh, and check out this giant gap between the “Test Colors” button and the next section of content.

It would be nice to close this gap so the “yeah” and “naw” counters are visible in the test.

One of the many nice features of this site is a checkbox that allows you to see only the colors that passed the test, rather than viewing all of the tested colors. Unfortunately, that button does nothing with CSS disabled. However, I can still see which colors work and get the definitions for contrast ratio, large text, and small text directly in the result table.

Hiding and showing the terms is probably what the button does with CSS. The bummer is that I won’t know the purpose of those single letters (e.g. S and R) after the table headers. It’s also both ironic and confusing to see that message for all failing colors after the table because, well, there are passing colors in this list. What could be done is have hide it by default but conditionally inject it later if all the colors in a single test fail.

Pulling out DevTools, it turns out some of the white space at the top is the Hex Naw logo as a SVG file. The space above that is associated with other SVG symbols used for the page. By using a default color of black for the logo, this would help reduce some of the space. I made that quick change in DevTools and it makes a noticeable difference.

The size of the mobile menu and “X” icons can easily be reduced and be proportional to their viewBox attributes. Here’s one way to reduce the size of the mobile menu and "X" icons.

The second gap of space is caused by an SVG loader that appears while calculating color contrasts. This could be helped by specifying a much smaller, yet proportional, width and height exactly like the mobile menu and “X” icons.

I was able to reveal and resize the SVG loader icon in DevTools.

Adding an initial width and height to each SVG would definitely reduce the need to scroll. This is also what we can do to fix the gaps we saw in GitHub’s navigation as well.

Ultimately, Hex Naw remains pretty useful without CSS. I can still test colors, get passing and failing color results, and navigate around the page. It’s just too bad I wasn’t able to work with actual colors and had to work around those extra large SVG icons.

&#x1f44d; What the Site Does Well &#x1f4a1; What the Site Can Improve The site maintains good content hierarchy throughout the site. SVGs should be use a fallback fill color and use the height and width attributes. All of the elements are written semantically. Feedback for all failing colors could be dynamically added and removed to prevent awkward messaging. The tests themselves function properly with the exception of being able to show or hide information. Consider an alternative way to display color for the values being tested, like table cells with the background color attribute. Website 5: Stack Overflow The Stack Overflow homepage with CSS (left) and without CSS (right).

Like GitHub, Stack Overflow is one of those resources that many (if not most) of us keep in our back pocket because it helps find whether someone has already asked a development question and the answers to them.

On the page to ask a question, I see a bunch of blank bullet points above the main <textarea> element. I have no idea why those empty list items are there. I don’t see any of the formatting buttons either, but after messing around a bit, I found that they happen to be nothing more than blank list items. Perhaps fallback text or an SVG icon for each item would help identify what these are and do. They should be turned into real buttons as well.

It’s also still possible to get a list of similar questions while entering text into the title field. Every works here as expected, which is nice. Although, it is strange that the vote counts for each suggested question appears twice, once above the title as a link and again next to the title without being linked.

The “Ask a Question” page has a little awkward formatting, but the overall functionality is in tact and the page is relatively easy to navigate.

One of the key elements we all look for when landing on a Stack Overflow question page is that big green checkmark that indicates the correct answer out of all the submitted answers. But with CSS turned off, it’s hard to tell which answer was accepted because each answer in the list has a black checkmark. Even if the accepted answer is always at the top, there’s still no alternative or fallback indication without having to interact with the page. Additionally, there’s no indication if you have already up voted or down voted the question or any of the answers.

The question (left) next to the list of provided answers (right). We lose a lot of hierarchy when styles are taken away.

To sum up my experience on Stack Overflow, I was able to accomplish what I normally come to the site for: finding answers to a programming problem. That said, there were indeed a few opportunities for improvement and this site is a prime example of how design often relies on color to indicate hierarchy or value on a page, which was sorely missing from the question pages in this experiment.

&#x1f44d; What the Site Does Well &#x1f4a1; What the Site Can Improve Almost every element is written semantically. Use clear controls to identify editing tools while asking or answering questions. SVG icons use the width and height attributes. Consider a visual icon to distinguish the accepted answer from any other answers to a question. Lists of answers are clear and easy to scan. Consider a different method to indicate an up vote or a down vote besides color alone. Website 6: Wikipedia The Wikipedia homepage with CSS (left) and without CSS (right).

Wikipedia, the web’s primary point of reference! It’s an online staple and one of its appealing qualities is a sort of lack of design. This should make for an interesting test.

A few links down, we have a skip navigation option for the real navigation and search. The homepage header containing the globe image maintains its two column layout, and you may have guessed why: this is a table layout. While it may not be a usability issue, we know it isn’t semantic to rely on tables to create a layout. That was a relic of the way past when we didn’t have floats, flexbox, grid or any other way to handle content placement. That said, there are no noticeable usability issues or confusing elements on the page.

Let’s move on to what many of us spend the most time on in Wikipedia: an article entry. This is often the entry point to Wikipedia, especially for those of us that start by typing something into a search engine, then click on the Wikipedia search result.

Notice how similar the style-less page is to the styled page, even though it becomes a single column.

The bottom line is that this page is still extremely usable and hierarchical with CSS disabled. The layout goes down to a single column, but the content still flows in a logical order and even maintains bits of styling, thanks again to a reliance on tables and inline table properties.

One issue I bumped up against is the navigation. There is a “Jump to navigation” link in the header which indeed drops me down to the navigation when I click it. In case you’re wondering, the navigation is contained in the footer, which is the reason for needing to jump to it.

Navigation menu with stranded checkboxes above “Variants” and “More.”

There are seemingly random checkboxes above a couple of the navigation headings (specifically for “Variants” and “More”) and they appear to serve no purpose, although the checkbox above “More” becomes displays at a certain viewport width when CSS is enabled.

There actually is one odd thing in the navigation, and it’s a label-less button between the “In other projects” and “Languages” headings.

Hovering over the button provides a hint that it’s for language settings, but the button should at least have a title to make that clear up front.

Clicking that button, I’m still able to access the language settings, and it mostly works as expected. For example, the layout maintains a tabbed layout which is super functional.

In the Display tab, however, the “Language” and “Fonts” buttons do nothing. They probably are tabs as well, but at least I can see what they offer. Beside those buttons are two empty select menus that do absolutely nothing (the first one does become populated with ComicNeue, OpenDyslexic, and System font options when you check the checkbox). Looking at the “Input” tab, the writing language buttons still happen to function as tabs. I’m still able to select options other than English, Spanish, and Chinese.

Pressing the [...] button takes me to a list of languages at the top of the page.

The articles aren’t difficult to read at all without CSS and that’s because nearly every element is semantically correct and follows a consistent document hierarchy. One thing I did wonder was where the “Show/Hide” button that’s normally in the table of contents went. It turns out to be a lone checkbox, and the label is fake — it uses the content property on a pseudo-element in CSS to display the label.

Another issue in articles is that you have to spend time hunting images down when previewing them. Normally, clicking an image in the article sidebar will trigger a full-screen modal that contains a carousel of images. Without CSS, that carousel is gone and, in its place, is the image with a row of unlabeled buttons above it. That’s a bummer, but would be perfectly OK if the carousel wasn’t all the way down the page, opposite of where the clicked image is at the top of the page without an ability to jump down to it.

The image carousel is no longer contained in a modal, but at the end of the page.

I’d be careless if I didn’t mention that the Wikipedia logo was nowhere to be found on the article! It’s not even a white SVG on white. The link contains actually nothing:

<a class="mw-wiki-logo" href="/wiki/Main_Page" title="Visit the main page"></a>

Thankfully, the “Main page” link under “Navigation” is the another way back home without pressing the browser Back button. But, still feels odd to have no branding on the page when it does such a great job of it on the homepage.

Wikipedia’s HTML issues exist mostly in features I expect to be less often used rather than articles. They never hampered my reading experience in the long run.

&#x1f44d; What the Site Does Well &#x1f4a1; What the Site Can Improve The site maintains a clean structure and hierarchy. The logo placement could be moved (or added, in some cases) to the top of the page without a CSS background image. Skip links are used effectively for search and navigation. Buttons should include labels. The article content is semantic and easy to read. The image carousel on pages could load where the trigger occurs and use proper button labels for the controls. Ways to make CSS-less a better experience

CSS is a key component to the modern web. As we’ve seen up to this point, there are a number of sites that become next to un-unusable without it — and we’re counting some of the most recognizable and used sites in that mix. What we’ve seen is that, at best, the primary purpose for a site can still be accomplished, but there are hurdles along the way. Things like:

  • missing or semantically incorrect skip links
  • links that run together
  • oversized images that require additional scrolling
  • empty elements, like list items and button labels

Let’s see if we can compile these into a sort of list of best practices to consider for situations where CSS might be disabled or even unavailable.

Include a skip navigation link at the top of the document

Having a hidden link to skip the navigation is a must. Notice how most of the sites we looked at contained navigation links directly in the header. With CSS turned off, those navigations became long lists of links that would be so hard to tab or scroll through for any user. Having a link to skip that would make that experience much better.

The most basic HTML example I’ve seen is an anchor link that targets an ID where the main content begins.

<a href="#main">Skip to main content</a> <!-- etc. --> <main id="main"></main>

And, of course, we can throw a class name on that link to hide it visually so it is not displayed in the UI but still available for both keyboard users and when CSS happens to be off.

.skip-navigation { border: 0; clip: rect(1px, 1px, 1px, 1px); overflow: hidden; padding: 0; position: absolute; height: 1px; width: 1px; } /* Bonus points for adding :focus styles */ Leave whitespaces where they make sense

Another pain point we saw in a few cases were text links running together. Whether it was in the navigation, tags, or other linked up meta, we often saw links that were “glued together” in such a way that several individual links appeared to be one giant link. That’s either the result of hand-coding the links like that or an automated build task that compresses HTML and removes whitespaces in the process. Either way, the HTML winds up like this:

<a href="#">CSS</a><a href="#">JavaScript</a><a href="#">Python</a><a href="#">Swift</a>

We can keep the freedom to use spaces or line breaks though, even with CSS disabled. One idea is to lean on flexbox for positioning list elements when CSS is enabled. When CSS is disabled, the list items should stack vertically and display as list items by default.

If the items are tags and should still be separated, then traditional spacing methods like margins and padding are still great and we can rely on natural line breaks in the HTML to help with the style-less formatting. For example, here are line breaks in the HTML used to separate items, flexbox to remove spaces, then styled up in CSS to re-separated the items:

See the Pen
Handling Links in HTML Separated by Spaces or Line Breaks
by Jon Kantner (@jkantner)
on CodePen.

Use width and height attributes liberally

The biggest nuisance in this experiment may have been images exploding on the screen to the point that they dominate the content, take up an inordinate amount of space, and result in a hefty amount of scrolling for all users.

The fix here is rather straightforward because we have HTML attributes waiting for us to define them. Both images and SVG have methods for explicitly defining their width and height.

<img src="/path/to-image.jpg" width="40" height="40" /> <svg width="40px" height="40px" viewBox="0 0 200 200"> <polygon points="80,0 120,0 120,80 200,80 200,120 120,120 120,200 80,200 80,120 0,120 0,80 80,80" /> </svg> Prepare SVGs for a white background

Many of the large gaps on the sites we looked at looked like empty space, but they were really white SVGs that blew up to full size and blended into the white background.

So, yes, using the proper width and height attributes is a good idea to prevent monstrous icons, but we can also do something about that white-on-white situation. Using properties like fill and fill-rule as attributes will work here.

<!-- Icon will be red by default --> <svg viewBox="-241 243 16 16" width="100px" fill="#ff0000"> <path d="M-229.2,244c-1.7,0-3.1,1.4-3.8,2.8c-0.7-1.4-2.1-2.8-3.8-2.8c-2.3,0-4.2,1.9-4.2,4.2c0,4.7,4.8,6,8,10.6 c3.1-4.6,8-6.1,8-10.6C-225,245.9-226.9,244-229.2,244L-229.2,244z"/> </svg> /* ...and it’s still red when CSS is enabled */ svg { fill: #ff0000; }

See the Pen
Define SVG Width Attribute
by Geoff Graham (@geoffgraham)
on CodePen.

Label those buttons!

Lastly, if buttons are initially empty, they need to have visible fallback content. If they use a background image and a title for what the do, use a span containing the title text then add aria-hidden="true" so it doesn’t sound like the screen reader is reading the button label twice (e.g. VoiceOver says, “Add button Add” instead).

<button class="btn-icon" title="Add"> <span class="btn-label" aria-hidden="true">Add</span> </button>

Then the CSS can be something like this:

.btn-icon { background: url(path/to/icon.svg) 0 0 / 100% 100%; height: 40px; width: 40px; } .btn-label { display: block; overflow: hidden; height: 0; }

If there are <li> elements acting as buttons, they can remain, but they should be static, and the contents should be placed in a button.

Now, if the icon is an SVG, we can ensure the title tooltip can still be seen by using aria-labelledby and assigning the id to the title.

<button> <svg width="40px" height="40px" viewBox="0 0 200 200" aria-labelledby="btn-title"> <title id="btn-title">Add</title> <polygon points="80,0 120,0 120,80 200,80 200,120 120,120 120,200 80,200 80,120 0,120 0,80 80,80" /> </svg> </button> Conclusion

It can be easy to either forget or be afraid to check how a site appears when CSS isn’t available to make the UI look as good as intended. After a brief tour of the Non-CSS Web™, we saw just how important CSS is to the overall design and experience of sites, both small and large.

And, like any tool we have in our set, leaning too heavily on CSS to handle the functionality and behavior of elements can lead to poor experiences when it’s not around to do its magic. We’ve seen the same be true of sites that lean too heavily on JavaScript. This isn’t to say that we should not use them and rely on them, but to remember that they are not bulletproof on their own and need proper fallbacks to ensure an optimal experience is still available with or without our tooling.

Seen in that light, CSS is really a layer of progressive enhancement. The hierarchy, form controls, and other elements should also remain intact under their user agent styles. The look and feel, while important, is second when it comes to making sure elements are functional at their core.

The post That Time I Tried Browsing the Web Without CSS appeared first on CSS-Tricks.

Preload, prefetch and other link tags

Css Tricks - Wed, 04/24/2019 - 4:12am

Ivan Akulov has collected a whole bunch of information and know-how on making things load a bit more quickly with preload and prefetch. That's great in and of itself, but he also points to something new to me – the as attribute:

<link rel="preload" href="/style.css" as="style" />

Supposedly, this helps browsers prioritize when to download assets and which assets to load.

My favorite part of this post is Ivan’s quick summary at the end which clearly defines what all these different tags can be used for:

<link rel="preload"> – when you’ll need a resource in a few seconds
<link rel="prefetch"> – when you’ll need a resource on a next page
<link rel="preconnect"> – when you know you’ll need a resource soon, but you don’t know its full url yet

Make sure to check out our own post on the matter of prefetching, preloading, and prebrowsing, too. Adding these things to our links can make significant performance improvements and so check it out to add more resources to your performance toolbox.

Direct Link to ArticlePermalink

The post Preload, prefetch and other link tags appeared first on CSS-Tricks.

Choosing The Right UI Design Deliverables

Usability Geek - Tue, 04/23/2019 - 12:37pm
When I moved into an apartment of my own, my first purchase was a brand new, fully-stocked toolbox. After I got home and started to assemble some furniture, I opened my pristine toolbox, grabbed my...
Categories: Web Standards

Who Are Design Systems For?

Css Tricks - Tue, 04/23/2019 - 10:46am

Specific design systems, I mean. Design systems, as a concept, are something just about any site can benefit from.

A lot of hype goes into design systems these days. Just the other day, an organization's published their design system publicly and I got a slew of DMs, emails, and Slack messages encouraging me to check it out. "Looks good to me," I said. But I'm merely knocking on the hood of a new car, so to speak. I haven't sat in it. I haven't driven it around the block, let alone driven it cross-country or tried to dig Cheerios out from between the seats. I'm sure I'd have more opinions after building a site or 10 with it (excuse the mixed metaphors).

So that leads me to a few questions. Can I build a site with this design system? Should I build a site with it? Is it for me? Or wait... who is this for?

They all have accordions.

Well not all of them, but bear with me, because there is a point to be made.

Bootstrap has an accordion too! Developers totally understand Bootstrap.

Whatever you think of it, I don't see much confusion around Bootstrap. You link up the CSS, you use the HTML they give you and — &#x1f4a5; — you have components that are ready to rock.

It's possible that Bootstrap is a more of a "pattern library" than a "design system." I dunno. There is probably something to that distinction, but the naming semantics (if there are any) seem to be used interchangeably, so distinguishing Bootstrap as one or the other doesn't alleviate any confusion.

Developers reach for Bootstrap because...

  • It helps them build faster.
  • They get good quality "out of the box" if they aren't particularly great at HTML and CSS themselves.
  • They want to be accessible and Bootstrap has been through the accessibility ringer.
  • [Insert your reason.]

Appealing, yet these seem to be somewhat table stakes for any design system and not exclusive to Bootstrap alone.

Hmmmm... Maybe I'll have a gander around and choose a non-Bootstrap solution for my next project.

A lot of people are in this boat.

Maybe the next project is React so we want a design system that makes React a first-class citizen. Maybe we had trouble customizing Bootstrap to our liking. Maybe we just saw the default look of another design system and thought that would be a better fit. Maybe we are just bored of Bootstrap. Lots of reasons to look outside of Bootstrap, just as there are lots of reasons to look to it.

Since other design systems have accordions, too, can't I just... pick one?

Sorta?

One immediate consideration is the license. Salesforce's Lightning Design System is often pointed to as a leader in the world of design systems and has influenced a lot of the current thinking around them. Yet, it is not open source licensed. Actually, it is open source licensed. It uses BSD Clause-3 (MIT-like) for everything but the fonts and icons, which are Creative Commons Attribution-NoDerivatives 4.0. I'm told: "anyone could reuse the code in their project that don’t have anything to do with Salesforce. They just can’t reuse it in a way that’s mimicking the system too closely."

That's not a problem — it's probably a good thing for Lightning. It's not a general purpose grab-it-and-go for all web developers on Earth as the target audience. It's for Salesforce and the slew of teams on different development stacks building things for Salesforce. If you're not building a Salesforce thing, it's not for you.

Then why is it public and not some internal document for the Salesforce team? I can't answer for them, but as I understand it, Salesforce is so enormous that they have both internal and external teams using it. So, perhaps making Lightning a public document is the most useful way to make it available to everyone who needs it.

This is something we’re actively discussing on the SLDS team. What exactly does “open source” mean to design systems when the usage is so specific? Is it more “source available?

— Alexis Córdova (@acordova) April 9, 2019

There's also the nice side effect that they get good press for it, and that can't hurt hiring efforts. I've also heard having a public design system can spark interesting and useful conversations.

Carbon Design System, on the other hand, is open source licensed. They also have an entire section explaining who should use the system:

Carbon is the official implementation of the IBM Design Language for product and web designers, and represents an ever-growing ecosystem of design assets and guidance. With a comprehensive set of human interface guidelines, design kits, and documentation, Carbon helps designers work faster and smarter.

That doesn't quite tell me what I want to know. It looks like IBM stuff out of the box, so it's definitely for IBM.

It's open source so I can use it if I want to. But is it really for me and my random projects? Do they want me to use it for that? Am I, random developer, who they are thinking about with this project? Or is it IBM-first, random developer second?

Company first, the world second.

If a design system is by a company, then it's for the company. It might also be open source, but any ol' random developer who wants to use it isn't the target audience.

It might not even technically be a company who makes it. It could be a government!

One really great design system is the U.S. Web Design System, which just went 2.0. It's gorgeous! It looks very complete and has some great features. It's got a classy custom font, it was designed with incremental adoption in mind, it has both useful components as well as utilities, and was built atomically from design tokens. Perhaps the best feature is that it's extremely accessible because it has to be by law.

The U.S. Web Design System is mostly public domain, so you totally can use it. But it's not designed with you in mind; it's designed to help people who make website for the government.

(By the way, The U.S. Web Design System is open to contribution, which is pretty cool because it's a way you could make a significant impact on websites that are very important to people's lives.)

My mindset is that open source design systems are not meant be reused and spin up for yourself, but to learn from and apply to your own

— Mike Dick (@miked1ck) April 9, 2019

Here's another kicker: There is a spectrum of customizability to design systems, on purpose.

Even if you technically can use a public design system you've found and like, you might consider the customizability angle. There is a whole spectrum to this, but let's consider the extreme edges and middle:

  • Zero Customizability: We built this to strongly enforce consistency for ourselves.
  • Pre-Selected Variations: We've got accordions in three different colors.
  • BYO Theme: We'll give you a skeleton that loosely achieves the pattern and you apply the styles to your liking.

There are design systems at all points on this spectrum. Bootstrap might be in between the last two, where you get a fully styled theme, but customizability largely comes via setting Sass variables and that creates infinite variations.

Polaris, Shopify's design system, is open source, but definitely for Shopify stuff. They are intentionally not trying to do what Bootstrap does (they tell me). It's far more about enforced consistency and adhering to a cohesive brand than it is slapping together and customizing a page.

Material Design is definitely Google's thing. The story of Material Design is that Google has an absolute crapload of products across all sorts of platforms. This could so easily become a mess of inconsistent design and branding. Instead, Google develops Material Design and successfully ships it across what seems like their entire empire. An incredible success story in design systems. So I don't think it's off base to say that Material Design is by-Google for-Google.

But these days, they definitely encourage other developers to use it too. By default, that makes your thing look like a Google thing.

But they are actively trying to make Material Design more customizable so you can bring your own brand. So far, it looks like there is a Sketch plugin that helps with that. For us coders, their Material Components repo looks like it is built with Sass and many things are set up with variables you can override. See this tutorial about customizing.

There are lots of success stories with customizing Material Design. Companies like Lyft, Zappos, and NPR, who all have strong brand identities of their own, all use customized Material Design.

That makes the messaging for Material Design all the more tricky and interesting. It's very definitely for Google, but clearly it's also very definitely intended for anyone else who wants to use it. That messaging just might work as Google has the resources and perception to pull that off in a way that I would think it's harder for other company-branded design systems to do.

In case this isn't obvious (and I very much fear that it isn't), design systems aren't a commodity. We don't get to simply pick the one that has the nicest accordion and use it on the next project. We might not even be allowed to use it. It might be intentionally branded for a specific company. There are all kinds of factors to consider here.

My parting advice is actually to the makers of public design systems: clearly identify who this design system is for and what they are able to do with it.

I'd also like to note that everyone who I've brought this up to in the last few weeks has had different opinions about all this target audience messaging stuff in design systems. Of course, I'd love to read your comments about how you feel about it.

The post Who Are Design Systems For? appeared first on CSS-Tricks.

The Circle of a React Lifecycle

Css Tricks - Tue, 04/23/2019 - 5:44am

A React component goes through different phases as it lives in an application, though it might not be evident that anything is happening behind the scenes.

Those phases are:

  • mounting
  • updating
  • unmounting
  • error handling

There are methods in each of these phases that make it possible to perform specific actions on the component during that phase. For example, when fetching data from a network, you’d want to call the function that handles the API call in the componentDidMount() method, which is available during the mounting phase.

Knowing the different lifecycle methods is important in the development of React applications, because it allows us to trigger actions exactly when they’re needed without getting tangled up with others. We’re going to look at each lifecycle in this post, including the methods that are available to them and the types of scenarios we’d use them.

The Mounting Phase

Think of mounting as the initial phase of a component’s lifecycle. Before mounting occurs, a component has yet to exist — it’s merely a twinkle in the eyes of the DOM until mounting takes place and hooks the component up as part of the document.

There are plenty of methods we can leverage once a component is mounted: constructor() , render(), componentDidMount() and static getDerivedStateFromProps(). Each one is handy in it’s own right, so let’s look at them in that order.

constructor()

The constructor() method is expected when state is set directly on a component in order to bind methods together. Here is how it looks:

// Once the input component is mounting... constructor(props) { // ...set some props on it... super(props); // ...which, in this case is a blank username... this.state = { username: '' }; // ...and then bind with a method that handles a change to the input this.handleInputChange = this.handleInputChange.bind(this); }

It is important to know that the constructor is the first method that gets called as the component is created. The component hasn’t rendered yet (that’s coming) but the DOM is aware of it and we can hook into it before it renders. As a result, this isn’t the place where we’d call setState() or introduce any side effects because, well, the component is still in the phase of being constructed!

I wrote up a tutorial on refs a little while back, and once thing I noted is that it’s possible to set up ref in the constructor when making use of React.createRef(). That’s legit because refs is used to change values without props or having to re-render the component with updates values:

constructor(props) { super(props); this.state = { username: '' }; this.inputText = React.createRef(); } render()

The render() method is where the markup for the component comes into view on the front end. Users can see it and access it at this point. If you’ve ever created a React component, then you’re already familiar with it — even if you didn’t realize it — because it’s required to spit out the markup.

class App extends React.Component { // When mounting is in progress, please render the following! render() { return ( <div> <p>Hello World!</p> </div> ) } }

But that’s not all that render() is good for! It can also be used to render an array of components:

class App extends React.Component { render () { return [ <h2>JavaScript Tools</h2>, <Frontend />, <Backend /> ] } }

...and even fragments of a component:

class App extends React.Component { render() { return ( <React.Fragment> <p>Hello World!</p> </React.Fragment> ) } }

We can also use it to render components outside of the DOM hierarchy (a la React Portal):

// We're creating a portal that allows the component to travel around the DOM class Portal extends React.Component { // First, we're creating a div element constructor() { super(); this.el = document.createElement("div"); } // Once it mounts, let's append the component's children componentDidMount = () => { portalRoot.appendChild(this.el); }; // If the component is removed from the DOM, then we'll remove the children, too componentWillUnmount = () => { portalRoot.removeChild(this.el); }; // Ah, now we can render the component and its children where we want render() { const { children } = this.props; return ReactDOM.createPortal(children, this.el); } }

And, of course, render() can — ahem — render numbers and strings...

class App extends React.Component { render () { return "Hello World!" } }

...as well as null or Boolean values:

class App extends React.Component { render () { return null } } componentDidMount()

Does the componentDidMount() name give away what it means? This method gets called after the component is mounted (i.e. hooked to the DOM). In another tutorial I wrote up on fetching data in React, this is where you want to make a request to obtain data from an API.

We can have your fetch method:

fetchUsers() { fetch(`https://jsonplaceholder.typicode.com/users`) .then(response => response.json()) .then(data => this.setState({ users: data, isLoading: false, }) ) .catch(error => this.setState({ error, isLoading: false })); }

Then call the method in componentDidMount() hook:

componentDidMount() { this.fetchUsers(); }

We can also add event listeners:

componentDidMount() { el.addEventListener() }

Neat, right?

static getDerivedStateFromProps()

It’s kind of a long-winded name, but static getDerivedStateFromProps() isn’t as complicated as it sounds. It’s called before the render() method during the mounting phase, and before the update phase. It returns either an object to update the state of a component, or null when there’s nothing to update.

To understand how it works, let’s implement a counter component which will have a certain value for its counter state. This state will only update when the value of maxCount is higher. maxCount will be passed from the parent component.

Here’s the parent component:

class App extends React.Component { constructor(props) { super(props) this.textInput = React.createRef(); this.state = { value: 0 } } handleIncrement = e => { e.preventDefault(); this.setState({ value: this.state.value + 1 }) }; handleDecrement = e => { e.preventDefault(); this.setState({ value: this.state.value - 1 }) }; render() { return ( <React.Fragment> <section className="section"> <p>Max count: { this.state.value }</p> <button onClick={this.handleIncrement} class="button is-grey">+</button> <button onClick={this.handleDecrement} class="button is-dark">-</button> </section> <section className="section"> <Counter maxCount={this.state.value} /> </section> </React.Fragment> ) } }

We have a button used to increase the value of maxCount, which we pass to the Counter component.

class Counter extends React.Component { state={ counter: 5 } static getDerivedStateFromProps(nextProps, prevState) { if (prevState.counter < nextProps.maxCount) { return { counter: nextProps.maxCount }; } return null; } render() { return ( <div className="box"> <p>Count: {this.state.counter}</p> </div> ) } }

In the Counter component, we check to see if counter is less than maxCount. If it is, we set counter to the value of maxCount. Otherwise, we do nothing.

You can play around with the following Pen below to see how that works on the front end:

See the Pen
getDerivedStateFromProps
by Kingsley Silas Chijioke (@kinsomicrote)
on CodePen.

The Updating Phase

The updating phase occurs when a component when a component’s props or state changes. Like mounting, updating has its own set of available methods, which we’ll look at next. That said, it’s worth noting that both render() and getDerivedStateFromProps() also get triggered in this phase.

shouldComponentUpdate()

When the state or props of a component changes, we can make use of the shouldComponentUpdate() method to control whether the component should update or not. This method is called before rendering occurs and when state and props are being received. The default behavior is true. To re-render every time the state or props change, we’d do something like this:

shouldComponentUpdate(nextProps, nextState) { return this.state.value !== nextState.value; }

When false is returned, the component does not update and, instead, the render() method is called to display the component.

getSnapshotBeforeUpdate()

One thing we can do is capture the state of a component at a moment in time, and that’s what getSnapshotBeforeUpdate() is designed to do. It’s called after render() but before any new changes are committed to the DOM. The returned value gets passed as a third parameter to componentDidUpdate().

It takes the previous state and props as parameters:

getSnapshotBeforeUpdate(prevProps, prevState) { // ... }

Use cases for this method are kinda few and far between, at least in my experience. It is one of those lifecycle methods you may not find yourself reaching for very often.

componentDidUpdate()

Add componentDidUpdate() to the list of methods where the name sort of says it all. If the component updates, then we can hook into it at that time using this method and pass it previous props and state of the component.

componentDidUpdate(prevProps, prevState) { if (prevState.counter !== this.state.counter) { // ... } }

If you ever make use of getSnapshotBeforeUpdate(), you can also pass the returned value as a parameter to componentDidUpdate():

componentDidUpdate(prevProps, prevState, snapshot) { if (prevState.counter !== this.state.counter) { // .... } } The Unmounting Phase

We’re pretty much looking at the inverse of the mounting phase here. As you might expect, unmounting occurs when a component is wiped out of the DOM and no longer available.

We only have one method in here: componentWillUnmount()

This gets called before a component is unmounted and destroyed. This is where we would want to carry out any necessary clean up after the component takes a hike, like removing event listeners that may have been added in componentDidMount(), or clearing subscriptions.

// Remove event listener componentWillUnmount() { el.removeEventListener() } The Error Handling Phase

Things can go wrong in a component and that can leave us with errors. We’ve had error boundary around for a while to help with this. This error boundary component makes use of some methods to help us handle the errors we could encounter.

getDerivedStateFromError()

We use getDerivedStateFromError() to catch any errors thrown from a descendant component, which we then use to update the state of the component.

class ErrorBoundary extends React.Component { constructor(props) { super(props); this.state = { hasError: false }; } static getDerivedStateFromError(error) { return { hasError: true }; } render() { if (this.state.hasError) { return ( <h1>Oops, something went wrong :(</h1> ); } return this.props.children; } }

In this example, the ErrorBoundary component will display “Oops, something went wrong” when an error is thrown from a child component. We have a lot more info on this method in a wrap up on goodies that were released in React 16.6.0.

componentDidCatch()

While getDerivedStateFromError() is suited for updating the state of the component in cases where where side effects, like error logging, take place, we ought to make use of componentDidCatch() because it is called during the commit phase, when the DOM has been updated.

componentDidCatch(error, info) { // Log error to service }

Both getDerivedStateFromError() and componentDidCatch() can be used in the ErrorBoundary component:

class ErrorBoundary extends React.Component { constructor(props) { super(props); this.state = { hasError: false }; } static getDerivedStateFromError(error) { return { hasError: true }; } componentDidCatch(error, info) { // Log error to service } render() { if (this.state.hasError) { return ( <h1>Oops, something went wrong :(</h1> ); } return this.props.children; } } And that’s the lifecycle of a React component!

There’s something neat about knowing how a React component interacts with the DOM. It’s easy to think some “magic” happens and then something appears on a page. But the lifecycle of a React component shows that there’s order to the madness and it’s designed to give us a great deal of control to make things happen from the time the component hits the DOM to the time it goes away.

We covered a lot of ground in a relatively short amount of space, but hopefully this gives you a good idea of not only how React handles components, but what sort of capabilities we have at various stages of that handling. Feel free to leave any questions at all if anything we covered here is unclear and I’d be happy to help as best I can!

The post The Circle of a React Lifecycle appeared first on CSS-Tricks.

Netlify Functions for Sending Emails

Css Tricks - Tue, 04/23/2019 - 4:26am

Let's say you're rocking a JAMstack-style site (no server-side languages in use), but you want to do something rather dynamic like send an email. Not a problem! That's the whole point of JAMstack. It's not just static hosting. It's that plus doing anything else you wanna do through JavaScript and APIs.

Here's the setup: You need a service to help you send the email. Let's just pick Sparkpost out of a hat. There are a number of them, and I'll leave comparing their features and pricing to you, as we're doing something extremely basic and low-volume here. To send an email with Sparkpost, you hit their API with your API key, provide information about the email you want to send, and Sparkpost sends it.

So, you'll need to run a little server-side code to protect your API key during the API request. Where can you run that code? A Lambda is perfect for that (aka a serverless function or cloud function). There are lots of services to help you run these, but none are easier than Netlify, where you might be hosting your site anyway.

Get Sparkpost ready

I signed up for Sparkpost and made sure my account was all set up and verified. The dashboard there will give you an API key:

Toss that API Key into Netlify

Part of protecting our API key is making sure it's only used in server-side code, but also that we keep it out of our Git repository. Netlify has environment variables that expose it to functions as needed, so we'll plop it there:

Let's spin up Netlify Dev, as that'll make this easy to work with

Netlify Dev is a magical little tool that does stuff like run our static site generator for us. For the site I'm working on, I use Eleventy and Netlify Dev auto-detects and auto-runs it, which is super neat. But more importantly, for us, it gives us a local URL that runs our functions for testing.

Once it's all installed, running it should look like this:

In the terminal screenshot above, it shows the website itself being spun up at localhost:8080, but it also says:

? Lambda server is listening on 59629

That'll be very useful in a moment when we're writing and testing our new function — which, by the way, we can scaffold out if we'd like. For example:

netlify functions:create --name hello-world

From there, it will ask some questions and then make a function. Pretty useful to get started quickly. We'll cover writing that function in a moment, but first, let's use this...

Sparkpost has their own Node lib

Sparkpost has an API, of course, for sending these emails. We could look at those docs and learn how to hit their URL endpoints with the correct data.

But things get even easier with their Node.js bindings. Let's get this set up by creating all the folders and files we'll need:

/project ... your entire website or whatever ... /functions/ /send-email/ package.json send-email.js

All we need the package.json file for is to yank in the Sparkpost library, so npm install sparkpost --save-dev will do the trick there.

Then the send-email.js imports that lib and uses it:

const SparkPost = require('sparkpost'); const client = new SparkPost(process.env.SPARKPOST); exports.handler = function(event, context, callback) { client.transmissions .send({ content: { from: 'chris@css-tricks.com', subject: 'Hello, World!', html: "<html><body><p>My cool email.</p></body></html>" }, recipients: [{ address: 'chriscoyier@gmail.com' }] }); }

You'll want to look at their docs for error handling and whatnot. Again, we've just chosen Sparkpost out of a hat here. Any email sending service will have an API and helper code for popular languages.

Notice line 2! That's where we need the API key, and we don't need to hard-code it because Netlify Dev is so darn fancy that it will connect to Netlify and let us use the environment variable from there.

Test the function

When Netlify Dev is running, our Lamba functions have that special port they are running. We'll be able to have a URL like this to run the function:

http://localhost:34567/.netlify/functions/send-email

This function is set up to run when it's hit, so we could simply visit that in a browser to run it.

Testing

Maybe you'll POST to this URL. Maybe you'll send the body of the email. Maybe you'll send the recipient's email address. It would be nice to have a testing environment for all of this.

Well, we can console.log() stuff and see it in the terminal, so that's always handy. Plus we can write our functions to return whatever, and we could look at those responses in some kind of API testing tool, like Postman or Insomnia.

It works!

I'll leave it to you to get fancy with it ;)

The post Netlify Functions for Sending Emails appeared first on CSS-Tricks.

Could Grouping HTML Classes Make Them More Readable?

Css Tricks - Mon, 04/22/2019 - 9:45am

You can have multiple classes on an HTML element:

<div class="module p-2"></div>

Nothing incorrect or invalid there at all. It has two classes. In CSS, both of these will apply:

.module { } .p-2 { } const div = document.querySelector("div"); console.log(div.classList.contains("module")); // true console.log(div.classList.contains("p-3")); // false

But what about grouping them? All we have here is a space-separated string. Maybe that's fine. But maybe we can make things more clear!

Years ago, Harry Roberts talked about grouping them. He wrapped groups of classes in square brackets:

<div class="[ foo foo--bar ] [ baz baz--foo ]">

The example class names above are totally abstract just to demonstrate the grouping. Imagine they are like primary names and variations as one group, then utility classes as another group:

<header class="[ site-header site-header-large ] [ mb-10 p-15 ]">

Those square brackets? Meaningless. Those are there to visually represent the groups to us developers. Technically, they are also classes, so if some sadist wrote .[ {}, it would do stuff in your CSS. But that's so unlikely that, hopefully, the clarity from the groups outweighs it and is more helpful.

That example above groups the primary name and a variation in one group and some example utility classes in another group.

I'm not necessarily recommending that approach. They are simply groups of classes that you might have.

Here's the same style of grouping, with different groups:

<button class="[ link-button ] [ font-base text-xs color-primary ] [ js-trigger ]" type="button" hidden>

That example has a single primary name, utility classes with different naming styles, and a third group for JavaScript specific selectors.

Harry wound up shunning this approach a few years ago, saying that the look of it was just too weird for the variety of people and teams he worked with. It caused enough confusion that the benefits of grouped classes weren't worth it. He suggested line breaks instead:

<div class="media media--large testimonial testimonial--main">

That seems similarly clear to me. The line breaks in HTML are totally fine. Plus, the browser will have no trouble with that and JSX is generally written with lots of line breaks in HTML anyway because of how much extra stuff is plopped onto elements in there, like event handlers and props.

Perhaps we combine the ideas of line breaks as separators and identified groups... with emojis!

See the Pen
Grouping Classes
by Chris Coyier (@chriscoyier)
on CodePen.

Weird, but fun. Emojis are totally valid there. Like the square brackets, they could also do things if someone wrote a class name for them, but that's generally unlikely and something for a team to talk about.

Another thing I've seen used is data-* attributes for groups instead of classes, like...

<div class="primary-name" data-js="js-hook-1 js-hook-2" data-utilities="padding-large" >

You can still select and style based on attributes in both CSS and JavaScript, so it's functional, though slightly less convenient because of the awkward selectors like [data-js="js-hook-1"] and lack of convenient APIs like classList.

How about you? Do you have any other clever ideas for class name groups?

The post Could Grouping HTML Classes Make Them More Readable? appeared first on CSS-Tricks.

So, You Wanna Submit a Proposal to Speak at an Event

Css Tricks - Mon, 04/22/2019 - 4:38am

You’ve been scouring the web for upcoming events. You’ve subscribed to Developer Avocados and you’ve bookmarked conferences.css-tricks.com. And now you’ve found a call for proposals (CFP) that you can’t wait to enter. You quickly fill out the online form and your pinky races towards the Enter button...

Stop. Take a deep breath. And move slowly away from the keyboard.

As a conference organizer, I’ve gone through hundreds — if not thousands — of speaking proposals. While many are excellent, there are always a bunch that show a profound misunderstanding of the event, audience, and duties of a speaker. These are the ones that immediately get dumped onto the "No Thanks" list on my Trello board. And, as a regular speaker, I’ve learned more than a few things about getting proposals accepted.

While there’s no magic bullet for fast tracking your talk, there are a number of habits you can develop and questions you can ask yourself before hitting "submit" to improve your chances of getting invited to events. If you’re a fan of checklists, I’ve put one together to guide you through the process of submitting a proposal.

It’s even available on CodePen. &#x1f609;

See the Pen
The CFP Checklist
by Jason Rodriguez (@rodriguezcommaj)
on CodePen.

Start with some research

The first thing before submitting a proposal is to research the heck out of the event.

There are a ton of events out there, each with its own unique audience and vibe. Some are big, some are small; some have huge budgets and some are bootstrapped and brand new. Your first task as a potential speaker is to learn as much as you can about the event to make sure that you’re a good fit for it and the audience. There are a few ways to do this.

First, check out the website to get a feel for the event. See when and where it is, check out past years (if there are any), and read every last bit of copy on the site. A few things to keep an eye out for: an FAQ page, a CFP page, info about sponsorships or speaking opportunities, lists of past speakers, and a hashtag. The event hashtag is important, as that will allow you to check out hype and past attendee experiences on Twitter, as well to as get a sense of excitement about the upcoming event. If there isn’t a hashtag, or all of the comments about the event are terrible, then perhaps it’s time to move on to the next CFP.

Next, do a search on YouTube, Speaker Deck, SlideShare, and Notist for past talks and slide decks. These will give you a great idea of what to expect at the event and what kinds of talks go over well with the audience.

After you’ve completed a first pass of research, it’s time to answer some key questions:

  • When and where is the event?
  • Who’s organizing it?
  • Do they have a code of conduct?
  • Do they value diversity and inclusion?
  • Are they looking for specific topics or proposals?
  • Do they cover travel/hotel?
  • Do they pay speakers?
  • Most importantly: who is their audience?

You may not be able to find an answer to all of these, but try your hardest. Feel free to reach out to organizers — most are happy to answer questions for potential speakers, and the more you know, the better you’ll be able to determine whether or not you’re a good fit for their event.

Add focus your idea

After you’ve done your research, it’s time to focus in on your proposal idea. Chances are good that you’re hunting around for events with a talk idea already in mind, but even so, you should take a few steps to make it’s as compelling for organizers as possible.

The main question you want to answer when developing a talk idea is, "What will attendees get out of my session?" This is where knowing about the audience and event — all of that research — pays off.

Far too many would-be speakers submit proposals for the wrong reasons. Many think of events as marketing and sales opportunities for their business. Others are looking to make a name for themselves so they can start charging on the speakers circuit. But the best talks come from sharing personal experiences, challenges, and solutions to problems you’ve experienced in your own work.

By researching the audience, you can determine what’s likely to be important to them. You get a feel for their challenges and interests, and you can think more deeply about how your experiences and skills can best serve them. Try to forget about the actual organizers and making a pitch to them, and instead focus all of your energy on clearly communicating how attendees’ lives and work will be improved after they sit in on your session.

A great exercise is to list out the key things attendees would take away from your talk. Try to focus on 3-5 things that people can put to work when they get back home. Making them as actionable as possible is a fantastic idea. While some proposals are all about inspiration, wrapping practical advice into inspirational examples is an excellent way to make that inspiration stick in people’s minds.

Another suggestion is to run your idea by colleagues, friends, or your partner. Put together a two-minute summary, stand up in front of them, and give them the ol’ elevator pitch. Not only will this force you to add a clear focus to your idea, but it’ll let you know if you’re ready to get up on stage in front of strangers. If you can’t give a short talk in a few minutes now, then you should probably sit back down and prepare some more before answering that call for proposals.

Craft your proposal into something worth reading

Finally, it’s time to craft your proposal and get it ready to submit.

Most CFPs consist of an online form. They can range from a few questions to multiple pages of inputs, but you’ll be filling something out for organizers to review. Although some speakers are able to fly through the forms and quickly hit "Submit," I’d recommend prepping your CFPs outside of the form first.

Open up a text file or make a note in your app of choice on one side of your screen and the CFP form on the other. Go through each field in the form and write down your response in your notes. Putting together a rough draft outside of the form gives you the opportunity to think through your answers and edit them until they clearly reflect your focused idea and the value for attendees. What’s better is that you can take that note and share it with someone you trust and respect. Gather feedback from them and use it to further refine your proposal.

A lot of CFP ask for supporting materials. These can be videos showing that you are a clear communicator, links to your website or social media accounts showing your personal interests, or even slides from previous talks. Instead of fumbling around and potentially timing out the CFPs form (and having to start all over), collect all of those materials in your note or a folder on your computer. If you’re a seasoned speaker, make sure you curate your materials to show your best and most recent talks.

Submit and wait

OK. You’ve done the research. You’ve focused your idea. You’ve even drafted the answers to the CFP, pitched the idea to your partner in the kitchen, and collected feedback from a co-worker or two. It’s time to scratch that itch and submit your proposal.

Go back to the CFP form, open up your notes and resources, and start copying and pasting. Take your time to work through the form and triple-check that you’ve filled everything out. Attach any supporting materials (seriously, how many times have we all sent an email that says "See attached file" without actually attaching anything?) and take a deep breath. Scroll to the top and read through every response as many times as you need to before you feel comfortable submitting.

Now, press "Submit." Do a little celebration, take another deep breath, and move on with your life.

It can take a long time for organizers to process submissions and figure out an agenda. Try to be patient. It’s tempting to email organizers and ask about the status of your proposal, but resist the urge. Organizers are extraordinarily busy — with the conference and their full-time jobs — and should be left to review proposals instead of fielding emails from impatient potential speakers.

A good organizer will get back to you when they’re ready and let you know the status of your submission — good or bad. If they don’t, chances are the event wasn’t that great to begin with. The key thing is to try to forget about your submission as much as possible (while still keeping the event on your calendar, just in case) and focus on more important things. Not only will this ease your anxiety but you’ll be in for a wonderful surprise when your proposal is accepted.

Speaking at events can be incredibly rewarding. Sure, it’s massively time-consuming and, depending on your disposition, extremely stressful, but it’s an excellent way to build connections and help others in the industry. While you could start spamming every event with proposals, your chances of being invited to speak all hinge on the amount of preparation you put into your submission. Taking the time to make sure you’re a good fit for an event, that you understand the audience, and that you have a focus and are able to clearly communicate your idea will up the odds of you standing onstage, clicking through slides, and (hopefully) solving some problems for the folks that paid to be there.

I’m definitely not the first person to write about answering CFPs. There are a ton of good tips out there for crafting the perfect proposal. Here are a few of my favorites:

Finally, if you have any hesitation about not being "good enough" to speak at conferences, read this excellent post from Sara Wachter-Boettcher. Then start crafting that perfect proposal.

The post So, You Wanna Submit a Proposal to Speak at an Event appeared first on CSS-Tricks.

Inclusively Hidden

Css Tricks - Fri, 04/19/2019 - 9:31am

Scott O'Hara recently published "Inclusively Hidden," a nice walkthrough of the different ways to hide things on the web. Nothing is ever cut and dry when it comes to the web! What complicates this is that hidden begs the question: hidden for whom? Different answers to that have different solutions:

  • Hidden for everyone? display: none; or visibility: hidden; or the hidden attribute. (But watch out for that hidden attribute, says Monica Dinculescu.)
  • Hidden visually, but present for assistive tech? A .screen-reader-only class with a smattering of properties to do the job correctly.
  • Hidden for assistive tech, but not visually? The aria-hidden="true" attribute/value.

It's worth grokking all this because it's is a perfect example of why HTML and CSS is not some easy bolt-on skill for front-end web development. This is critical stuff that isn't done as correctly as it should be.

If you like video, I did one called "Hiding Things with CSS" that goes over a lot of this.

As I write this, I'm freshly back from Smashing Conf in San Francisco. Sara Soueidan had a wonderful talk that covered some "hiding things" situations that are even less intuitive than what we might be accustomed to seeing.

One thing she covered was the inert attribute and how it can be used to skip interactive elements from keyboard tabbing. It can even be used on a parent element, nullifying everything inside it. I understood that part, but not entirely why it's useful since it seems like you might as well use display: none; if an element is hidden and the elements inside aren't meant to be in focus. But I'm sure it's my lack of understanding, so I'm looking forward to Sara's video to come out so I can re-watch it. It had to do with maintaining a non-awkward tabbing order.

Another thing Sara covered is that some folks who use assistive technology also tend to explore touch screens with haptics, moving about the page with their fingers looking for interactive elements. If you, say, replace a native checkbox with a styled checkbox, it's possible to do that in a way thats mostly accessible by using a real checkbox that you hide and replace with a graphic, but Sara demoed how you can resize the checkbox over the top of the replacement and hide visually with opacity: 0; — that ensures someone can still find the element by touch. That doesn't seem to be the default way this kind of thing is taught or built, so it's great to see Sara calling it out. Yet another example of HTML and CSS being nuanced and tricky languages.

Direct Link to ArticlePermalink

The post Inclusively Hidden appeared first on CSS-Tricks.

Tabs: It’s Complicated™

Css Tricks - Fri, 04/19/2019 - 9:14am

I've said before one quick and powerful thing you can learn as a front-end developer just getting starting with JavaScript is changing classes.

const button = document.querySelector(".my-button"); const element = document.querySelector(".content"); button.addEventListener("click", function() { element.classList.toggle("sparkles"); });

We could use that skill to build some tabs, right? Right.

We got this.

Say we have this changing classes ability in our skillset now and we need to build a tabbed interface. If we just add a little more code that deals with click handlers, we could probably wire up some simple tabs, like this:

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

Totally functional tabs. I might pat myself on the back a little here. See how I used those anchor links to create jump links between the link and the tabbed section? That's mighty semantic, don't you think? The tabs are accessible with a keyboard, have focus styles, and can be activated with the Return key.

Did we win? Case closed? Perfect tabs?

Nothing is ever so easy, is it?

One issue here is that we didn't do anything special with keyboard handling, which tabbed interfaces may require. Heydon Pickering wrote about this:

Unlike a same-page link, a tab does not move the user to the associated section/panel of content. It just reveals the content visually. This is advantageous to sighted users (including sighted screen reader users) who wish to flit between different sections without having to wade back up the page each time they want to choose a new one.

This comes with an unfortunate side effect: If the user wishes to move to a section by keyboard and interact with its internal content, they have to step through any tabs to the right of the current tab, which are in focus order.

Turns out there is a whole checklist of other behavioral things tabs interfaces can and should be doing. In Heydon's explanation, the Tab key actually acts as a way to jump from the tab itself to the content related to that tab, actually moving the focus. Shift+Tab brings them back. Then the arrow keys are used to change tabs. All this requires more JavaScript and even some HTML to allow for the focus state... plus a sprinkle of aria-* attributes which I lack the expertise to explain you why they are important at all.

In the end, like this:

See the Pen
Tab Interface (PE)
by Heydon (@heydon)
on CodePen.

So the question becomes: are our class-changing skills actually a detriment to the web because they don't account for things like this? Is doing things with whatever basic tools we have a net loss for web accessibility? I dunno. Too big of a question for my little brain. It's interesting to consider, though.

Part of it comes down to muscle memory.

If we learn to code tabs like that first demo there, we'll tend to reach for that over and over so long as nobody bites our fingers off for doing it. I coded that demo in about three minutes because I've done it so many times. Creating those tabs is certainly part of my muscle memory.

There is plenty of talk about JavaScript frameworks being a scourge across the web because they seem to be ushering in an era of worst-in-class accessibility. But what if your muscle memory for building tabs was reaching for a pre-built tabs UI that brings along all the right functionality and left styling largely to you?

That's what Reach UI tabs are (which assumes we're working with React...).

I'm not telling you to go out and switch your projects to React so you can get some free tabs, but React is already massive. If good patterns like this become the defacto choice, then it's possible that the effect is a net gain on accessibility. Seems possible to me, anyway. It might just stop me from poorly hand-coding a tabbed interface for the 359th time.

The post Tabs: It’s Complicated™ appeared first on CSS-Tricks.

How to Get a Progressive Web App into the Google Play Store

Css Tricks - Fri, 04/19/2019 - 4:29am

PWA (Progressive Web Apps) have been with us for some time now. Yet, each time I try explaining it to clients, the same question pops up: "Will my users be able to install the app using app stores?" The answer has traditionally been no, but this changed with Chrome 72 which shipped a new feature called TWA (Trusted Web Activities).

Trusted Web Activities are a new way to integrate your web-app content such as your PWA with yourAndroid app using a protocol based on Custom Tabs.

In this article, I will use Netguru’s existing PWA (Wordguru) and explain step-by-step what needs to be done to make the application available and ready to be installed straight from the Google Play app store.

Some of the things we cover here may sound silly to any Android Developers out there, but this article is written from the perspective of a front-end developer, particularly one who has never used Android Studio or created an Android Application. Also, please do note that a lot of what we're covering here is still extremely experimental since it's limited to Chrome 72.

Step 1: Set up a Trusted Web Activity

Setting up a TWA doesn’t require you to write any Java code, but you will need to have Android Studio. If you’ve developed iOS or Mac software before, this is a lot like Xcode in that it provides a nice development environment designed to streamline Android development. So, grab that and meet me back here.

Create a new TWA project in Android Studio

Did you get Android Studio? Well, I can’t actually hear or see you, so I’ll assume you did. Go ahead and crack it open, then click on "Start a new Android Studio project." From there, let’s choose the "Add No Activity" option, which allows us to configure the project.

The configuration is fairly straightforward, but it’s always good to know what is what:

  • Name The name of the application (but I bet you knew that).
  • Package name: An identifier for Android applications on the Play Store. It must be unique, so I suggest using the URL of the PWA in reverse order (e.g. com.netguru.wordguru).
  • Save location: Where the project will exist locally.
  • Language: This allows us to select a specific code language, but there’s no need for that since our app is already, you know, written. We can leave this at Java, which is the default selection.
  • Minimum API level: This is the version of the Android API we’re working with and is required by the support library (which we’ll cover next). Let’s use API 19.

There are few checkboxes below these options. Those are irrelevant for us here, so leave them all unchecked, then move on to Finish.

Add TWA Support Library

A support library is required for TWAs. The good news is that we only need to modify two files to fill that requirement and the both live in the same project directory: Gradle Scripts. Both are named build.gradle, but we can distinguish which is which by looking at the description in the parenthesis.

There’s a Git package manager called JitPack that’s made specifically for Android apps. It’s pretty robust, but the bottom line is that it makes publishing our web app a breeze. It is a paid service, but I’d say it’s worth the cost if this is your first time getting something into the Google Play store.

Editor Note: This isn’t a sponsored plug for JitPack. It’s worth calling out because this post is assuming little-to-no familiarity with Android Apps or submitting apps to Google Play and it has less friction for managing an Android App repo that connects directly to the store. That said, it’s totally not a requirement.

Once you’re in JitPack, let’s connect our project to it. Open up that build.gradle (Project: Wordguru) file we just looked at and tell it to look at JitPack for the app repository:

allprojects { repositories { ... maven { url 'https://jitpack.io' } ... } }

OK, now let’s open up that other build.gradle file. This is where we can add any required dependencies for the project and we do indeed have one:

// build.gradle (Module: app) dependencies { ... implementation 'com.github.GoogleChrome:custom-tabs-client:a0f7418972' ... }

TWA library uses Java 8 features, so we’re going to need enable Java 8. To do that we need to add compileOptions to the same file:

// build.gradle (Module: app) android { ... compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } ... }

There are also variables called manifestPlaceholders that we’ll cover in the next section. For now, let’s add the following to define where the app is hosted, the default URL and the app name:

// build.gradle (Module: app) android { ... defaultConfig { ... manifestPlaceholders = [ hostName: "wordguru.netguru.com", defaultUrl: "https://wordguru.netguru.com", launcherName: "Wordguru" ] ... } ... } Provide app details in the Android App Manifest

Every Android app has an Android App Manifest (AndroidManifest.xml) which provides essential details about the app, like the operating system it’s tied to, package information, device compatibility, and many other things that help Google Play display the app’s requirements.

The thing we’re really concerned with here is Activity (<activity>). This is what implements the user interface and is required for the "Activities" in "Trusted Web Activities."

Funny enough, we selected the "Add No Activity" option when setting up our project in Android Studio and that’s because our manifest is empty and contains only the application tag.

Let’s start by opening up the manfifest file. We’ll replace the existing package name with our own application ID and the label with the value from the manifestPlaceholders variables we defined in the previous section.

Then, we’re going to actually add the TWA activity by adding an <activity> tag inside the <application> tag.

<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.netguru.wordguru"> // highlight <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="${launcherName}" // highlight android:supportsRtl="true" android:theme="@style/AppTheme"> <activity android:name="android.support.customtabs.trusted.LauncherActivity" android:label="${launcherName}"> // highlight <meta-data android:name="android.support.customtabs.trusted.DEFAULT_URL" android:value="${defaultUrl}" /> // highlight <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> <intent-filter android:autoVerify="true"> <action android:name="android.intent.action.VIEW"/> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.BROWSABLE"/> <data android:scheme="https" android:host="${hostName}"/> // highlight </intent-filter> </activity> </application> </manifest>

And that, my friends, is Step 1. Let’s move on to Step 2.

Step 2: Verify the relationship between the website and the app

TWAs require a connection between the Android application and the PWA. To do that, we use Digital Asset Links.

The connection must be set on both ends, where TWA is the application and PWA is the website.

To establish that connection we need to modify our manifestPlaceholders again. This time, we need to add an extra element called assetStatements that keeps the information about our PWA.

// build.gradle (Module: app) android { ... defaultConfig { ... manifestPlaceholders = [ ... assetStatements: '[{ "relation": ["delegate_permission/common.handle_all_urls"], ' + '"target": {"namespace": "web", "site": "https://wordguru.netguru.com"}}]' ... ] ... } ... }

Now, we need to add a new meta-data tag to our application tag. This will inform the Android application that we want to establish the connection with the application specified in the manifestPlaceholders.

<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="${packageId}"> <application> ... <meta-data android:name="asset_statements" android:value="${assetStatements}" /> ... </application> </manifest>

That’s it! we just established the application to website relationship. Now let’s jump into the conversion of website to application.

To establish the connection in the opposite direction, we need to create a .json file that will be available in the app’s /.well-known/assetlinks.json path. The file can be created using a generator that’s built into Android Studio. See, I told you Android Studio helps streamline Android development!

We need three values to generate the file:

  • Hosting site domain: This is our PWA URL (e.g. https://wordguru.netguru.com/).
  • App package name: This is our TWA package name (e.g. com.netguru.wordguru).
  • App package fingerprint (SHA256): This is a unique cryptographic hash that is generated based on Google Play Store keystore.

We already have first and second value. We can get the last one using Android Studio.

First we need to generate signed APK. In the Android Studio go to: Build ? Generate Signed Bundle or APK ? APK.

Next, use the existing keystore, if you already have one. If you need one, go to "Create new…" first.

Then let’s fill out the form. Be sure to remember the credentials as those are what the application will be signed with and they confirm your ownership of the application.

This will create a keystore file that is required to generate the app package fingerprint (SHA256). This file is extremely important as it is works as a proof that you are the owner of the application. If this file is lost, you will not be able to do any further updates to your application in the store.

Next up, let’s select type of bundle. In this case, we’re choosing "release" because it gives us a production bundle. We also need to check the signature versions.

This will generate our APK that will be used later to create a release in Google Play store. After creating our keystore, we can use it to generate required app package fingerprint (the SHA256).

Let’s head back to Android Studio, and go to Tools ? App Links Assistant. This will open a sidebar that shows the steps that are required to create a relationship between the application and website. We want to go to Step 3, "Declare Website Association" and fill in required data: Site domain and Application ID. Then, select the keystore file generated in the previous step.

After filling the form press "Generate Digital Asset Links file" which will generate our assetlinks.json file. If we open that up, it should look something like this:

[{ "relation": ["delegate_permission/common.handle_all_urls"], "target": { "namespace": "android_app", "package_name": "com.netguru.wordguru", "sha256_cert_fingerprints": ["8A:F4:....:29:28"] } }]

This is the file we need to make available in our app’s /.well-known/assetlinks.json path. I will not describe how to make it available on that path as it is too project-specific and outside the scope of this article.

We can test the relationship by clicking on the "Link and Verify" button. If all goes well, we get a confirmation with "Success!"

Yay! We’ve established a two-way relationship between our Android application and our PWA. It’s all downhill from here, so let’s drive it home.

Step 3: Get required assets

Google Play requires a few assets to make sure the app is presented nicely in the store. Specifically, here’s what we need:

  • App Icons: We need a variety of sizes, including 48x48, 72x72, 96x96, 144x144, 192x192… or we can use an adaptive icon.
  • High-res Icon: This is a 512x512 PNG image that is used throughout the store.
  • Feature Graphic: This is a 1024x500 JPG or 24-bit PNG (no alpha) banner that Google Play uses on the app details view.
  • Screenshots: Google Play will use these to show off different views of the app that users can check out prior to downloading it.

Having all those, we can proceed to the Google Play Store developers console and publish the application!

Step 4: Publish to Google Play!

Let’s go to the last step and finally push our app to the store.

Using the APK that we generated earlier (which is located in the AndroidStudioProjects directory), we need to go to the Google Play console to publish our application. I will not describe the process of publishing an application in the store as the wizard makes it pretty straightforward and we are provided step-by-step guidance throughout the process.

It may take few hours for the application to be reviewed and approved, but when it is, it will finally appear in the store.

If you can’t find the APK, you can create a new one by going to Build ? Generate signed bundle / APK ? Build APK, passing our existing keystore file and filling the alias and password that we used when we generated the keystore. After the APK is generated, a notice should appear and you can get to the file by clicking on the "Locate" link.

Congrats, your app is in Google Play!

That’s it! We just pushed our PWA to the Google Play store. The process is not as intuitive as we would like it to be, but still, with a bit of effort it is definitely doable, and believe me, it gives that great filling at the end when you see your app displayed in the wild.

It is worth pointing out that this feature is still very much early phase and I would consider it experimental for some time. I would not recommend going with a production release of your application for now because this only works with Chrome 72 and above — any version before that will be able to install the app, but the app itself will crash instantly which is not the best user experience.

Also, the official release of custom-tabs-client does not support TWA yet. If you were wondering why we used raw GitHub link instead of the official library release, well, that’s why.

The post How to Get a Progressive Web App into the Google Play Store appeared first on CSS-Tricks.

Faking env() to Use it Now

Css Tricks - Thu, 04/18/2019 - 7:21am

There is already an env() function in CSS, but it kinda came out of nowhere as an Apple thing for dealing with "The Notch" but it has made it's way to be a draft spec. The point will be for UAs or authors to declare variables that cannot be changed. Global const for CSS, sorta.

That spec doesn't seem to suggest how we'll actually set those env() values just yet. If you want them now, the easiest way to fake them would be using regular ol' CSS custom properties and simply not change them.

But if you want that env() syntax though, there is a PostCSS plugin for emulating it. The way the plugin handles them is through a JavaScript file that declares them.

postcssCustomProperties({ importFrom: 'path/to/file.js' /* module.exports = { environmentVariables: { '--branding-padding': '20px', '--branding-small': '600px' } } */ });

Having them start life as JavaScript is interesting, as it means we could perhaps have a single place to set variables that are accessible both to JavaScript and CSS.

That's what Harry Nicholls covers more in his article, "Why you should use CSS env()" like some gotchas when dealing with units and such. But if you really needed a single source for unchangeable variables in both CSS and JavaScript, then I'd say this is a good way to go — and could potentially be ripped out once support for env() formally arrives.

The post Faking env() to Use it Now appeared first on CSS-Tricks.

Syndicate content
©2003 - Present Akamai Design & Development.