Web Standards

The “Inside” Problem

Css Tricks - Mon, 05/20/2019 - 6:36am

So, you're working on a design. You need a full-width container element because the design has a background-color that goes from edge-to-edge horizontally. But the content inside doesn’t necessarily need to be edge-to-edge. You want to:

  1. Limit the width (for large screens)
  2. Pad the edges
  3. Center the content

It's "the inside problem" in web layout. It's not hard, it's just that there are lots of considerations.

The "inside" issue. Centered, max-width/padding containers inside full-width color bands.

What's your favorite pattern?

(Just a fun every day thing with many possible solutions to consider!) pic.twitter.com/pNYf5YsQMp

— Chris Coyier (@chriscoyier) March 14, 2019

The classic solution is an outer and inner container.

The parent element is naturally as wide as it's own parent, and let's assume that's the <body> element, or the entire width of the browser window. That takes the background-color and pads the left and right sides. The inside element is what limits the width inside and centers.

<footer> <div class="inside"> Content </div> </footer> footer { --contentWidth: 400px; background: lightcoral; padding: 2rem 1rem; } .inside { max-width: var(--contentWidth); margin: 0 auto; }

This is what my brain reaches for first. Doesn't use anything fancy and feels perfectly understandable. That "inside" element isn't wonderfully desirable, only because it feels like busywork to remember to add it to the markup each time this pattern is used, but it does the trick with few other downsides.

See the Pen
Classic "inside" element
by Chris Coyier (@chriscoyier)
on CodePen.

What if you only can use a single element?

These type of limitations aren't my favorite, because I feel like a healthy project allows designers and developers to have whatever kind of control over the final HTML, CSS, and JavaScript output they need to do the best possible job. But, alas, sometimes you’re in a weird position as a contractor or have legacy CMS issues or whatever.

If you only have a single element to work with, padding sorrrrrta kinnnnda works. The trick is to use calc() and subtract half of the content’s maximum width from 100%.

<footer> Content </footer> footer { --contentWidth: 600px; background: lightcoral; padding: 2rem calc((100% - var(--contentWidth)) / 2); }

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

The problem here is that it doesn't prevent edge-touching, which might make this entirely unacceptable. Maybe you could select elements inside (paragraphs and whatnot...) and add padding to those (with a universal selector, like footer > *). It's tempting to put padding way up on the <body> or something to prevent edge-touching, but that doesn't work because we want that edge-to-edge background color.

What if you're already inside a container you can't control and need to break out of it?

Well, you can always do the ol' full-width utility thing. This will work in a centered container of any width:

.full-width { width: 100vw; margin-left: 50%; transform: translateX(-50%); }

But that leaves the content inside at full width as well. So, you'd need to turn to an inside element again.

See the Pen
Full width element with inside element
by Chris Coyier (@chriscoyier)
on CodePen.

Also, as soon as you have a vertical scrollbar, that 100vw value will trigger an obnoxious horizontal scrollbar. Some sites can pull off something like this to get rid of that scroll:

body { overflow-x: hidden; }

That’s pretty nice. If you can't do that, though, you might need to set an explicit width on the scrollbar, then subtract that from 100vw.

body { scrollbar-width: 20px; /* future standards way */ } body::-webkit-scrollbar { /* long-standing webkit way */ width: 20px; } .full-width { width: calc(100vw - 20px); }

Even that kinda sucks as it means the full-width container isn't quite full width when there is no vertical scrolling. I'd love to see CSS step it up here and help, probably with improved viewport units handling.

There are a variety of other ways of handling this full-width container thing, like Yanking to the edges with margins and such. However, they all ultimately need viewport units and suffer from the same scrollbar-related fate as a result.

If you can definitely hide the overflow-x on the parent, then extreme negative-margin and positive-padding can do the trick.

This is kinda cool in that it uses nothing modern at all. All very old school CSS properties.

See the Pen
Full Width Bars Using Negative Margins
by Chris Coyier (@chriscoyier)
on CodePen.

Can CSS Grid or Flexbox help here?

Meh. Not really.

I mean, sure, you could set up a three-column grid and place the content in the center column, while using the outside columns as padding. I don't think that's a particularly compelling use of grid and it adds complication for no benefit — that is, unless you're already using and taking advantage of grid at this scope.

Fake the edges instead.

There is no law that the background-color needs to come from one single continuous element. You could always "fake" the left and right sides by kicking out a huge box-shadow or placing a pseudo element wherever needed.

We cover various techniques around that here.

The post The “Inside” Problem appeared first on CSS-Tricks.

The “Inside” Problem

Css Tricks - Mon, 05/20/2019 - 6:36am

So, you're working on a design. You need a full-width container element because the design has a background-color that goes from edge-to-edge horizontally. But the content inside doesn’t necessarily need to be edge-to-edge. You want to:

  1. Limit the width (for large screens)
  2. Pad the edges
  3. Center the content

It's "the inside problem" in web layout. It's not hard, it's just that there are lots of considerations.

The "inside" issue. Centered, max-width/padding containers inside full-width color bands.

What's your favorite pattern?

(Just a fun every day thing with many possible solutions to consider!) pic.twitter.com/pNYf5YsQMp

— Chris Coyier (@chriscoyier) March 14, 2019

The classic solution is an outer and inner container.

The parent element is naturally as wide as it's own parent, and let's assume that's the <body> element, or the entire width of the browser window. That takes the background-color and pads the left and right sides. The inside element is what limits the width inside and centers.

<footer> <div class="inside"> Content </div> </footer> footer { --contentWidth: 400px; background: lightcoral; padding: 2rem 1rem; } .inside { max-width: var(--contentWidth); margin: 0 auto; }

This is what my brain reaches for first. Doesn't use anything fancy and feels perfectly understandable. That "inside" element isn't wonderfully desirable, only because it feels like busywork to remember to add it to the markup each time this pattern is used, but it does the trick with few other downsides.

See the Pen
Classic "inside" element
by Chris Coyier (@chriscoyier)
on CodePen.

What if you only can use a single element?

These type of limitations aren't my favorite, because I feel like a healthy project allows designers and developers to have whatever kind of control over the final HTML, CSS, and JavaScript output they need to do the best possible job. But, alas, sometimes you’re in a weird position as a contractor or have legacy CMS issues or whatever.

If you only have a single element to work with, padding sorrrrrta kinnnnda works. The trick is to use calc() and subtract half of the content’s maximum width from 100%.

<footer> Content </footer> footer { --contentWidth: 600px; background: lightcoral; padding: 2rem calc((100% - var(--contentWidth)) / 2); }

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

The problem here is that it doesn't prevent edge-touching, which might make this entirely unacceptable. Maybe you could select elements inside (paragraphs and whatnot...) and add padding to those (with a universal selector, like footer > *). It's tempting to put padding way up on the <body> or something to prevent edge-touching, but that doesn't work because we want that edge-to-edge background color.

What if you're already inside a container you can't control and need to break out of it?

Well, you can always do the ol' full-width utility thing. This will work in a centered container of any width:

.full-width { width: 100vw; margin-left: 50%; transform: translateX(-50%); }

But that leaves the content inside at full width as well. So, you'd need to turn to an inside element again.

See the Pen
Full width element with inside element
by Chris Coyier (@chriscoyier)
on CodePen.

Also, as soon as you have a vertical scrollbar, that 100vw value will trigger an obnoxious horizontal scrollbar. Some sites can pull off something like this to get rid of that scroll:

body { overflow-x: hidden; }

That’s pretty nice. If you can't do that, though, you might need to set an explicit width on the scrollbar, then subtract that from 100vw.

body { scrollbar-width: 20px; /* future standards way */ } body::-webkit-scrollbar { /* long-standing webkit way */ width: 20px; } .full-width { width: calc(100vw - 20px); }

Even that kinda sucks as it means the full-width container isn't quite full width when there is no vertical scrolling. I'd love to see CSS step it up here and help, probably with improved viewport units handling.

There are a variety of other ways of handling this full-width container thing, like Yanking to the edges with margins and such. However, they all ultimately need viewport units and suffer from the same scrollbar-related fate as a result.

If you can definitely hide the overflow-x on the parent, then extreme negative-margin and positive-padding can do the trick.

This is kinda cool in that it uses nothing modern at all. All very old school CSS properties.

See the Pen
Full Width Bars Using Negative Margins
by Chris Coyier (@chriscoyier)
on CodePen.

Can CSS Grid or Flexbox help here?

Meh. Not really.

I mean, sure, you could set up a three-column grid and place the content in the center column, while using the outside columns as padding. I don't think that's a particularly compelling use of grid and it adds complication for no benefit — that is, unless you're already using and taking advantage of grid at this scope.

Fake the edges instead.

There is no law that the background-color needs to come from one single continuous element. You could always "fake" the left and right sides by kicking out a huge box-shadow or placing a pseudo element wherever needed.

We cover various techniques around that here.

The post The “Inside” Problem appeared first on CSS-Tricks.

Creating a Diversity Scholarship Program for Your Conference

Css Tricks - Mon, 05/20/2019 - 4:27am

My partner and I ran a design and development conference company for eight years. During that time, we produced hundreds of hours of conferences, both on-site and online. Diversity scholarships were only becoming a typical conference offering around the time we decided to sunset our business. So, when we committed to collaborate on an updated ARTIFACT conference, I knew right away I wanted to make Diversity Scholarships available.

We always worked on making our events inclusive, so adding a program that would enhance that inclusion even more seemed like a no-brainer. When I started to research how to create a diversity scholarship program, though, the only examples I could find were finished programs, and not much documentation about the thinking or planning that created them. It’s not unusual to improvise a solution to a problem and make changes on the fly, in fact it's pretty routine when you run a small business. A diversity scholarship program was something I wanted to get right, though?—?or at least as “right” as possible?—?the first time around. I decided to look a little deeper than what was available online.

Tech conference organizers: have you offered diversity scholarships for your events? Would you be willing to answer a few questions about it? PM or @ me if interested. TIA!

Other sentient beings reading this: Can I get an RT to reach as many organizers as possible? Thanks!

— Ari Stiles (@ari4nne) March 11, 2019

Twitter helped me find conference organizers who had created and run diversity scholarship programs. I ended up talking to several organizers about their experiences, in addition to comparing a couple dozen programs and applications online.

Between sessions at the Open Source Summit (photo courtesy of the Linux Foundation) Before we dive in

There are two types of readers I’d like to address:

  1. If you don’t think the lack of diversity in tech is a problem, or don’t see why a scholarship program is necessary, this article is not for you. It is written with the assumption that the reader is already convinced of the merits of diversity, and is looking for ways to build a more diverse audience at the conferences or tech events they host; or
  2. If you are overwhelmed by the lack-of-diversity-in-tech issue, so much that you feel uncomfortable even addressing it, you are not alone. The problem is systemic, with deep, historical roots. It’s important to remember that you alone cannot solve the problems of an entire industry with one program or one event. Focus instead on what you can create, even with limited resources. Ask for help when you need it?—?most conference organizers I’ve met are glad to help.
From the beginning

So much of the planning for an inclusive conference takes place before you even begin talking about things like diversity scholarships. If your destination city is a relatively inexpensive and easy place to visit; if your venue is accessible and you’ve made plans for accommodations like live captioning; if your ticket prices are reasonable; and if your speaker lineup is genuinely diverse, you’ve got a strong foundation to build on.

Most of this can be accomplished with research. Cities popular with tourists tend to have reasonable transportation and accommodation prices. Cities with big tech hubs often have large, sometimes state-of-the art meeting spaces to hold conferences. Finding cities that have both can be a challenge, but the combination ultimately makes your conference more accessible to different types of attendees.

Creating a diverse lineup of speakers may attract a more diverse set of attendees (left to right: Sample speaker lineups from Hopper Celebration, Alterconf, and Clarity Conference)

A little more work may have to go into your speaker lineup. Although there has been some progress on this issue, the majority of tech conferences still mostly feature white men. There have been plenty of articles written on how to create a diverse speaker lineup, but one of my favorite tips is to focus on your conference content first and foremost. Thinking in terms of content makes it easier to look past a potential speaker’s popularity. It also works against your natural bias toward picking “friends” or people you have worked with before. By focusing instead on the content a speaker provides, you can evaluate how that content might add to your overall theme and how it might affect your audience. Curating content is more work than just lining up a group of well-known speakers, but it pays off in the form of a more focused conference and?—?usually?—?a more diverse lineup.

You'll also need to encourage open discussion among your co-organizers about diversity issues. My first job in conference planning was for South by SouthWest Interactive (SXSWi), and I feel lucky to have gotten my start working in an environment where these discussions were regular, open, and just “part of the process.” As with any skill, the more you practice talking about diversity, the easier it becomes.

Craft Conference has put together a video about their diversity program. These testimonials may help further the conversation with your colleagues.

Ask yourself why

Diversity and equity scholarship programs have become popular offerings at tech conferences for many reasons. We need more diversity in the industry, and the current thinking is that more diverse conferences can create more leadership and presentation opportunities for underrepresented populations. Diversity can lead to more robust discussions, too. This goal stated plainly on the Web site for #Perfmatters, run by Estelle Weyl:

"We want to ensure the conversation is stimulating and help everyone see their own Web app issues from new and different perspectives. For that, we need attendees with different perspectives. While we love everyone, conferences where all attendees come from corporations with generous continuing education budgets aren’t as interesting for participants as when attendees represent different work and life experiences."

It can be useful to do a little soul-searching to think about why you and your co-organizers want to do this. “More than anything,” says Tenessa Gemelke, organizer of Confab, “we wanted to remove obstacles, not just check boxes.” It’s easy to tell ourselves that because we’ve recruited a few women or people of color, we’ve “taken care of” conference diversity and we can move on to the next task. The needs of your diversity scholarship recipients are not checklist items?—?they are the building blocks of a more inclusive community.

Brainstorming a bit about the reasons you want to build a diversity scholarship program can help you set goals, identify problems specific to your target audience, and define limits. You might even discover that you have secondary objectives, which is not unusual.

Justin Reese is the Founder of Code & Supply and co-creator of several conferences based in Pittsburgh, PA. In addition to the traditional uses for diversity scholarships, he and his staff occasionally use scholarship funds to send up-and-coming hometown speakers to other cities. “We want people to see the talent and resources we have here in Pittsburgh,” says Reese. He and his team think of Code & Supply scholarships as a way to showcase local talent and build a robust, diverse tech community in their home town.

At ARTIFACT, we think of diversity and inclusion as the future of technology. So, in addition to building a robust, inclusive community, we see our diversity scholarship program as a vital part of a forward-thinking conference. Techniques and workflow change not only because of new gadgets and platforms, but because of new audiences and different types of teams.

Taking stock

Once you’ve settled on your “why,” it’s best to determine your “what”?—?as in, what you have to offer. Do you have any resources or perks on hand that will require no help from sponsors? For example, some conferences have more space than they need. Can you give some tickets away for free, or at a discount? Or if you have limited space, can you make a few free or discounted tickets possible by bumping up the cost of your other tickets? Make a list of what you can offer for free or from simple changes to your conference plan.

Other services that you might consider offering through your diversity scholarship program:

  • Assisting with travel
  • Assisting with accommodations
  • Meal stipends
  • On-site childcare
  • On-site nursing / feeding spaces

Some organizers even make travel and hotel reservations for their diversity scholarship attendees. It makes sense?—?most conferences already make these arrangements for their presenters, so it’s easy to do it for a few more people. This service may help scholarship dollars stretch a little further too, if the extra travel or booked rooms are available at a bulk discount.

If you want to offer more than just the basics, you will probably have to work with sponsors. The good news here is that sponsors often enjoy investing in diversity initiatives. Before approaching a potential sponsor, though, it’s wise to be clear on how you plan to spend the money. Consider creating a one-sheet that states your goals, the underrepresented groups you are trying to recruit, and what perks the sponsor can expect for participating. This way, you have something to leave behind for sponsors who want to think it over or who need to present the idea to others before it gets approval. Be sure to include your contact information.

Set your goals

It’s useful to think about how many diversity scholarships you’d like to offer in an ideal situation. In practice, that perfect number will probably drop based on your budget or lack of space, but having a lofty goal may encourage you to try a little harder.

Among the conference organizers I spoke with, the number of diversity scholarship recipients ranged from two to fifteen percent of total ticket sales. Those with higher numbers started with higher goals.

Attendees at JSCamp Barcelona Making it happen

Figuring out the logistics of a diversity scholarship plan may be the most complicated part of the process. Trying to figure out how to juggle all the tasks involved is what spurred me to do all this research in the first place!

Implementation will include some combination of the following steps, not necessarily in this order:

Put someone in charge

Your entire staff may be involved with processing diversity scholarships, but it’s a good idea to have one person oversee the whole program for the sake of continuity. There is a great deal of communication involved with this process, so it helps to choose a point person with strong organization and communication skills. The most significant qualification, though, is a real passion for creating a diverse conference community.

Create a reasonable timeline

With input from your team, set application deadlines, reviewing deadlines, and scholarship offer deadlines. Every organizer I spoke with suggested making these deadlines early in the process and sticking to them.

You’ll need enough time to review applications and make scholarship offers early enough to give your attendees time to plan. Remember that they might have to request time off work, make family care arrangements, and deal with other obligations. People from out of town need at least two months notice, and international attendees may need three months or more. Early deadlines help everyone. No one in your organization wants to review applications at the last minute anyway, since conference planning gets more intense in the weeks leading up to the event.

Any unclaimed scholarship resources can be used by qualified local attendees in the weeks leading up to your event. Since they don't have to factor in travel or accommodations, it is easier for local attendees to make plans at the last minute.

Make your scholarship program easy to find

Devote a page to your diversity scholarship program on your site, then link to that page as reasonably often as possible. If you can‘t list it in your main menu, consider linking it from the site footer and from the ticket sales page, in addition to posting about it regularly on social media.

Clearly state who qualifies for aid

The list may vary a bit based on your typical audience, but we chose the following criteria:

  • People of color
  • Indigenous persons
  • People with disabilities
  • People who identify as LGBTQIA+
  • Women
  • Veterans and new graduates just beginning their tech careers
  • Full-time students
  • People who work for nonprofit/educational/government institution with limited funds
  • People who are 55 years old or older
  • People who are currently unemployed / underemployed
  • People experiencing temporary financial hardship

Be sure to list the types of aid available (determined earlier, when you were “taking stock"). It’s also good to let your applicants know that not every application will be accommodated, and that all applications will be verified.

Collect the information you need?

Most conferences use some kind of online application form to collect and organize data. If you are not able to code one yourself, Google Forms or Wufoo make it pretty easy to build a form. Keep the application as simple as you can?—?you’ll need:

  • name,
  • contact information,
  • the reason(s) they qualify for aid (instead of a blank field, consider listing qualifications on the form as a way of reiterating the types of attendees you are trying to recruit),
  • the type of aid they are requesting (again, listing they types of aid available will help applicants understand what’s possible), and
  • maybe a statement about why they want to attend or why they need aid at this time.

You’ll want the form to compile data in a way that will be easy to sort through later, like a spreadsheet.

Preserve the anonymity of your applicants

Asking for help in a society that values self-sufficiency over shared responsibility can be tough. Don’t make it harder by asking applicants to divulge too much personal information, participate in open interviews with committee members, or meet with sponsors as part of your program. If a committee will be reviewing applications, consider anonymizing the entries before review.

Verify applications

This should be an ongoing process for several reasons. Some applicants will qualify for your program for reasons that are not always verifiable, so the person doing the vetting may need to contact them and clarify the request.

Other applicants may either misunderstand or overlook your qualifying criteria. The most common mistake many applicants make is assuming they qualify for aid only because their employer won’t cover the cost of the conference. This is where additional information will help: why isn’t this covered? Does the company have very limited funds, or is their travel budget just maxed out already? Does the applicant qualify for a diversity scholarship on other grounds? Applicants should know early in the process if their application is refused or if more information is needed.

Evaluate applications

Once the application deadline is met, evaluation begins. If your applications have been properly vetted, then the hardest work is already done. If a committee is evaluating applications, it’s good to not only figure out a way to anonymize applications, but also to streamline the evaluation process. Maybe give each committee member two or three questions to rate for each applicant. Possible evaluation questions:

  • How clearly is the need for aid stated?
  • How much aid is needed?
  • How much would this attendee impact the conference?
  • How much would the conference impact this attendee?

These can be rated on a scale, maybe one to ten, with ten being highest. This makes calculating scores easy. Other data you might choose to consider: when was the application received? Do you want to consider more local applicants than those from out-of-town?

Make and process scholarship offers and refusals

Evaluations have been made, so you are probably left with a set of applicants you want to offer scholarships to, some applicants you are not sure about yet, and a few that you plan to refuse. Start by making offers to those applicants you want to help attend the conference. Clearly state how much help you are offering and a deadline for accepting or refusing the offer.

If you are working with a particularly long waiting list, or the process is going slowly (more than two weeks since you began awarding scholarships), it’s courteous to let people know they are on a waiting list.

At ARTIFACT, we are assuming that some applicants may have a change in plans and therefore may have to refuse the scholarship. In that case, we will be passing along their offer to the next person on our waiting list.

Once all the offers have been made and accepted, it’s time to email the rest of the applicants, thank them for their participation, and let them know they won’t be receiving a scholarship offer. If you can, it’s nice to offer something to those who didn’t receive a scholarship: maybe a discounted ticket if they still choose to attend, or an invitation to any after-hour events, where you have room for a few extra people.

Create feedback mechanisms

In addition to all the input you sought from your colleagues in the beginning, you’ll need feedback on every aspect of the program. Make that easy to do by including an email address or link to a feedback form on your scholarship description page, your application form, and anywhere else on your site that seems appropriate. Once you start awarding scholarships, make communication a high priority. Consider creating a way to collect anonymous feedback from scholarship awardees and sponsors—easier to do if you have a larger conference—to foster honest, less inhibited comments.

Wait and see (and listen)

Now that everything needed for your diversity scholarship program is in place, it’s time to follow your plan and take note of what works and what doesn’t. Stay flexible, as you may have to change some parts of your program on the fly. Keep thinking in terms of equity for all of your applicants, and communicate openly about any changes you make. Applicants are more likely to trust a transparent process.

Listen more than you talk. Always.

Scholarship recipients for the Tapia Conference, a conference that celebrates and nurtures diversity in computing Follow up

Once ARTIFACT 2019 has concluded, I’ll be compiling all of our results and feedback in one place and writing a follow-up to this article. Until then, I’d like to thank all the conference organizers who took the time to answer my questions about diversity scholarship programs: Tenessa Gemelke, Estelle Weyl, Justin Reese, Val Head, Dave Poole, Jenn Strater, Ádám Boros, and PJ Hagerty.

In the meantime, here are some other resources you might find helpful:

The post Creating a Diversity Scholarship Program for Your Conference appeared first on CSS-Tricks.

Creating a Diversity Scholarship Program for Your Conference

Css Tricks - Mon, 05/20/2019 - 4:27am

My partner and I ran a design and development conference company for eight years. During that time, we produced hundreds of hours of conferences, both on-site and online. Diversity scholarships were only becoming a typical conference offering around the time we decided to sunset our business. So, when we committed to collaborate on an updated ARTIFACT conference, I knew right away I wanted to make Diversity Scholarships available.

We always worked on making our events inclusive, so adding a program that would enhance that inclusion even more seemed like a no-brainer. When I started to research how to create a diversity scholarship program, though, the only examples I could find were finished programs, and not much documentation about the thinking or planning that created them. It’s not unusual to improvise a solution to a problem and make changes on the fly, in fact it's pretty routine when you run a small business. A diversity scholarship program was something I wanted to get right, though?—?or at least as “right” as possible?—?the first time around. I decided to look a little deeper than what was available online.

Tech conference organizers: have you offered diversity scholarships for your events? Would you be willing to answer a few questions about it? PM or @ me if interested. TIA!

Other sentient beings reading this: Can I get an RT to reach as many organizers as possible? Thanks!

— Ari Stiles (@ari4nne) March 11, 2019

Twitter helped me find conference organizers who had created and run diversity scholarship programs. I ended up talking to several organizers about their experiences, in addition to comparing a couple dozen programs and applications online.

Between sessions at the Open Source Summit (photo courtesy of the Linux Foundation) Before we dive in

There are two types of readers I’d like to address:

  1. If you don’t think the lack of diversity in tech is a problem, or don’t see why a scholarship program is necessary, this article is not for you. It is written with the assumption that the reader is already convinced of the merits of diversity, and is looking for ways to build a more diverse audience at the conferences or tech events they host; or
  2. If you are overwhelmed by the lack-of-diversity-in-tech issue, so much that you feel uncomfortable even addressing it, you are not alone. The problem is systemic, with deep, historical roots. It’s important to remember that you alone cannot solve the problems of an entire industry with one program or one event. Focus instead on what you can create, even with limited resources. Ask for help when you need it?—?most conference organizers I’ve met are glad to help.
From the beginning

So much of the planning for an inclusive conference takes place before you even begin talking about things like diversity scholarships. If your destination city is a relatively inexpensive and easy place to visit; if your venue is accessible and you’ve made plans for accommodations like live captioning; if your ticket prices are reasonable; and if your speaker lineup is genuinely diverse, you’ve got a strong foundation to build on.

Most of this can be accomplished with research. Cities popular with tourists tend to have reasonable transportation and accommodation prices. Cities with big tech hubs often have large, sometimes state-of-the art meeting spaces to hold conferences. Finding cities that have both can be a challenge, but the combination ultimately makes your conference more accessible to different types of attendees.

Creating a diverse lineup of speakers may attract a more diverse set of attendees (left to right: Sample speaker lineups from Hopper Celebration, Alterconf, and Clarity Conference)

A little more work may have to go into your speaker lineup. Although there has been some progress on this issue, the majority of tech conferences still mostly feature white men. There have been plenty of articles written on how to create a diverse speaker lineup, but one of my favorite tips is to focus on your conference content first and foremost. Thinking in terms of content makes it easier to look past a potential speaker’s popularity. It also works against your natural bias toward picking “friends” or people you have worked with before. By focusing instead on the content a speaker provides, you can evaluate how that content might add to your overall theme and how it might affect your audience. Curating content is more work than just lining up a group of well-known speakers, but it pays off in the form of a more focused conference and?—?usually?—?a more diverse lineup.

You'll also need to encourage open discussion among your co-organizers about diversity issues. My first job in conference planning was for South by SouthWest Interactive (SXSWi), and I feel lucky to have gotten my start working in an environment where these discussions were regular, open, and just “part of the process.” As with any skill, the more you practice talking about diversity, the easier it becomes.

Craft Conference has put together a video about their diversity program. These testimonials may help further the conversation with your colleagues.

Ask yourself why

Diversity and equity scholarship programs have become popular offerings at tech conferences for many reasons. We need more diversity in the industry, and the current thinking is that more diverse conferences can create more leadership and presentation opportunities for underrepresented populations. Diversity can lead to more robust discussions, too. This goal stated plainly on the Web site for #Perfmatters, run by Estelle Weyl:

"We want to ensure the conversation is stimulating and help everyone see their own Web app issues from new and different perspectives. For that, we need attendees with different perspectives. While we love everyone, conferences where all attendees come from corporations with generous continuing education budgets aren’t as interesting for participants as when attendees represent different work and life experiences."

It can be useful to do a little soul-searching to think about why you and your co-organizers want to do this. “More than anything,” says Tenessa Gemelke, organizer of Confab, “we wanted to remove obstacles, not just check boxes.” It’s easy to tell ourselves that because we’ve recruited a few women or people of color, we’ve “taken care of” conference diversity and we can move on to the next task. The needs of your diversity scholarship recipients are not checklist items?—?they are the building blocks of a more inclusive community.

Brainstorming a bit about the reasons you want to build a diversity scholarship program can help you set goals, identify problems specific to your target audience, and define limits. You might even discover that you have secondary objectives, which is not unusual.

Justin Reese is the Founder of Code & Supply and co-creator of several conferences based in Pittsburgh, PA. In addition to the traditional uses for diversity scholarships, he and his staff occasionally use scholarship funds to send up-and-coming hometown speakers to other cities. “We want people to see the talent and resources we have here in Pittsburgh,” says Reese. He and his team think of Code & Supply scholarships as a way to showcase local talent and build a robust, diverse tech community in their home town.

At ARTIFACT, we think of diversity and inclusion as the future of technology. So, in addition to building a robust, inclusive community, we see our diversity scholarship program as a vital part of a forward-thinking conference. Techniques and workflow change not only because of new gadgets and platforms, but because of new audiences and different types of teams.

Taking stock

Once you’ve settled on your “why,” it’s best to determine your “what”?—?as in, what you have to offer. Do you have any resources or perks on hand that will require no help from sponsors? For example, some conferences have more space than they need. Can you give some tickets away for free, or at a discount? Or if you have limited space, can you make a few free or discounted tickets possible by bumping up the cost of your other tickets? Make a list of what you can offer for free or from simple changes to your conference plan.

Other services that you might consider offering through your diversity scholarship program:

  • Assisting with travel
  • Assisting with accommodations
  • Meal stipends
  • On-site childcare
  • On-site nursing / feeding spaces

Some organizers even make travel and hotel reservations for their diversity scholarship attendees. It makes sense?—?most conferences already make these arrangements for their presenters, so it’s easy to do it for a few more people. This service may help scholarship dollars stretch a little further too, if the extra travel or booked rooms are available at a bulk discount.

If you want to offer more than just the basics, you will probably have to work with sponsors. The good news here is that sponsors often enjoy investing in diversity initiatives. Before approaching a potential sponsor, though, it’s wise to be clear on how you plan to spend the money. Consider creating a one-sheet that states your goals, the underrepresented groups you are trying to recruit, and what perks the sponsor can expect for participating. This way, you have something to leave behind for sponsors who want to think it over or who need to present the idea to others before it gets approval. Be sure to include your contact information.

Set your goals

It’s useful to think about how many diversity scholarships you’d like to offer in an ideal situation. In practice, that perfect number will probably drop based on your budget or lack of space, but having a lofty goal may encourage you to try a little harder.

Among the conference organizers I spoke with, the number of diversity scholarship recipients ranged from two to fifteen percent of total ticket sales. Those with higher numbers started with higher goals.

Attendees at JSCamp Barcelona Making it happen

Figuring out the logistics of a diversity scholarship plan may be the most complicated part of the process. Trying to figure out how to juggle all the tasks involved is what spurred me to do all this research in the first place!

Implementation will include some combination of the following steps, not necessarily in this order:

Put someone in charge

Your entire staff may be involved with processing diversity scholarships, but it’s a good idea to have one person oversee the whole program for the sake of continuity. There is a great deal of communication involved with this process, so it helps to choose a point person with strong organization and communication skills. The most significant qualification, though, is a real passion for creating a diverse conference community.

Create a reasonable timeline

With input from your team, set application deadlines, reviewing deadlines, and scholarship offer deadlines. Every organizer I spoke with suggested making these deadlines early in the process and sticking to them.

You’ll need enough time to review applications and make scholarship offers early enough to give your attendees time to plan. Remember that they might have to request time off work, make family care arrangements, and deal with other obligations. People from out of town need at least two months notice, and international attendees may need three months or more. Early deadlines help everyone. No one in your organization wants to review applications at the last minute anyway, since conference planning gets more intense in the weeks leading up to the event.

Any unclaimed scholarship resources can be used by qualified local attendees in the weeks leading up to your event. Since they don't have to factor in travel or accommodations, it is easier for local attendees to make plans at the last minute.

Make your scholarship program easy to find

Devote a page to your diversity scholarship program on your site, then link to that page as reasonably often as possible. If you can‘t list it in your main menu, consider linking it from the site footer and from the ticket sales page, in addition to posting about it regularly on social media.

Clearly state who qualifies for aid

The list may vary a bit based on your typical audience, but we chose the following criteria:

  • People of color
  • Indigenous persons
  • People with disabilities
  • People who identify as LGBTQIA+
  • Women
  • Veterans and new graduates just beginning their tech careers
  • Full-time students
  • People who work for nonprofit/educational/government institution with limited funds
  • People who are 55 years old or older
  • People who are currently unemployed / underemployed
  • People experiencing temporary financial hardship

Be sure to list the types of aid available (determined earlier, when you were “taking stock"). It’s also good to let your applicants know that not every application will be accommodated, and that all applications will be verified.

Collect the information you need?

Most conferences use some kind of online application form to collect and organize data. If you are not able to code one yourself, Google Forms or Wufoo make it pretty easy to build a form. Keep the application as simple as you can?—?you’ll need:

  • name,
  • contact information,
  • the reason(s) they qualify for aid (instead of a blank field, consider listing qualifications on the form as a way of reiterating the types of attendees you are trying to recruit),
  • the type of aid they are requesting (again, listing they types of aid available will help applicants understand what’s possible), and
  • maybe a statement about why they want to attend or why they need aid at this time.

You’ll want the form to compile data in a way that will be easy to sort through later, like a spreadsheet.

Preserve the anonymity of your applicants

Asking for help in a society that values self-sufficiency over shared responsibility can be tough. Don’t make it harder by asking applicants to divulge too much personal information, participate in open interviews with committee members, or meet with sponsors as part of your program. If a committee will be reviewing applications, consider anonymizing the entries before review.

Verify applications

This should be an ongoing process for several reasons. Some applicants will qualify for your program for reasons that are not always verifiable, so the person doing the vetting may need to contact them and clarify the request.

Other applicants may either misunderstand or overlook your qualifying criteria. The most common mistake many applicants make is assuming they qualify for aid only because their employer won’t cover the cost of the conference. This is where additional information will help: why isn’t this covered? Does the company have very limited funds, or is their travel budget just maxed out already? Does the applicant qualify for a diversity scholarship on other grounds? Applicants should know early in the process if their application is refused or if more information is needed.

Evaluate applications

Once the application deadline is met, evaluation begins. If your applications have been properly vetted, then the hardest work is already done. If a committee is evaluating applications, it’s good to not only figure out a way to anonymize applications, but also to streamline the evaluation process. Maybe give each committee member two or three questions to rate for each applicant. Possible evaluation questions:

  • How clearly is the need for aid stated?
  • How much aid is needed?
  • How much would this attendee impact the conference?
  • How much would the conference impact this attendee?

These can be rated on a scale, maybe one to ten, with ten being highest. This makes calculating scores easy. Other data you might choose to consider: when was the application received? Do you want to consider more local applicants than those from out-of-town?

Make and process scholarship offers and refusals

Evaluations have been made, so you are probably left with a set of applicants you want to offer scholarships to, some applicants you are not sure about yet, and a few that you plan to refuse. Start by making offers to those applicants you want to help attend the conference. Clearly state how much help you are offering and a deadline for accepting or refusing the offer.

If you are working with a particularly long waiting list, or the process is going slowly (more than two weeks since you began awarding scholarships), it’s courteous to let people know they are on a waiting list.

At ARTIFACT, we are assuming that some applicants may have a change in plans and therefore may have to refuse the scholarship. In that case, we will be passing along their offer to the next person on our waiting list.

Once all the offers have been made and accepted, it’s time to email the rest of the applicants, thank them for their participation, and let them know they won’t be receiving a scholarship offer. If you can, it’s nice to offer something to those who didn’t receive a scholarship: maybe a discounted ticket if they still choose to attend, or an invitation to any after-hour events, where you have room for a few extra people.

Create feedback mechanisms

In addition to all the input you sought from your colleagues in the beginning, you’ll need feedback on every aspect of the program. Make that easy to do by including an email address or link to a feedback form on your scholarship description page, your application form, and anywhere else on your site that seems appropriate. Once you start awarding scholarships, make communication a high priority. Consider creating a way to collect anonymous feedback from scholarship awardees and sponsors—easier to do if you have a larger conference—to foster honest, less inhibited comments.

Wait and see (and listen)

Now that everything needed for your diversity scholarship program is in place, it’s time to follow your plan and take note of what works and what doesn’t. Stay flexible, as you may have to change some parts of your program on the fly. Keep thinking in terms of equity for all of your applicants, and communicate openly about any changes you make. Applicants are more likely to trust a transparent process.

Listen more than you talk. Always.

Scholarship recipients for the Tapia Conference, a conference that celebrates and nurtures diversity in computing Follow up

Once ARTIFACT 2019 has concluded, I’ll be compiling all of our results and feedback in one place and writing a follow-up to this article. Until then, I’d like to thank all the conference organizers who took the time to answer my questions about diversity scholarship programs: Tenessa Gemelke, Estelle Weyl, Justin Reese, Val Head, Dave Poole, Jenn Strater, Ádám Boros, and PJ Hagerty.

In the meantime, here are some other resources you might find helpful:

The post Creating a Diversity Scholarship Program for Your Conference appeared first on CSS-Tricks.

Footnotes That Work in RSS Readers

Css Tricks - Fri, 05/17/2019 - 10:52am

Feedbin is the RSS reader I'm using at the moment. I was reading one of Harry's blog posts on it the other day, and I noticed a nice little interactive touch right inside Feedbin. There was a button-looking element with the number one which, as it turned out, was a footnote. I hovered over it, and it revealed the note.

The HTML for the footnote on the blog post itself looks like this:

<p>...they’d managed to place 27.9MB of images onto the Critical Path. Almost 30MB of previously non-render blocking assets had just been turned into blocking ones on purpose with no escape hatch. Start render time was as high as 27.1s over a cable connection<sup id="fnref:1"> <a href="#fn:1" class="footnote">1</a></sup>.</p>

Just an anchor link that points to #fn:1, and the <sup> makes it look like a footnote link. This is how the styling would look by default:

The HTML for the list of footnotes at the bottom of the blog post looks like this:

<div class="footnotes"> <ol> <li id="fn:1"> <p>5Mb up, 1Mb down, 28ms RTT.&nbsp;<a href="#fnref:1" class="reversefootnote">&#x21a9;</a></p> </li> </ol> </div>

As a little side note, I notice Harry is using scroll-behavior to smooth the scroll. He's also got some nice :target styling in there.

All in all, we have:

  1. a link to go down and read the note
  2. a link to pop back up

Nothing special there. No fancy libraries or anything. Just semantic HTML. That should work in any RSS reader, assuming they don't futz with the hash links and maintain the IDs on the elements as written.

It's Feedbin that sees this markup pattern and decides to do the extra UI styling and fancy interaction. By inspecting what's going on, it looks like they hide the originals and replace them with their own special stuff:

Ah ha! A Bigfoot spotting! It's right in their source.

That means they fire off Bigfoot when articles are loaded and it does the trick. Like this:

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

That said, it's based on an already functional foundation. Lemme end this with that same markup pattern, and I'll try to look at it in different RSS readers to see what they do. Feel free to report what it does in your RSS reader of choice in the comments, if it does anything at all.

Azul is an abstract board game designed by Michael Kiesling and released by Plan B Games1 in 2017. From two to four players collect tiles to fill up a 5x5 player board. Players collect tiles by taking all the tiles of one color from a repository, and placing them in a row, taking turns until all the tiles for that round are taken. At that point, one tile from every filled row moves over to each player's 5x5 board, while the rest of the tiles in the filled row are discarded. Each tile scores based on where it is placed in relation to other tiles on the board. Rounds continue until at least one player has made a row of tiles all the way across their 5x5 board.

  1. Plan B makes other cool games like Century and Reef. 

The post Footnotes That Work in RSS Readers appeared first on CSS-Tricks.

Everything You Ever Wanted to Know About inputmode

Css Tricks - Fri, 05/17/2019 - 6:40am

The inputmode global attribute provides a hint to browsers for devices with onscreen keyboards to help them decide which keyboard to display when a user has selected any input or textarea element.

<input type="text" inputmode="" /> <textarea inputmode="" />

Unlike changing the type of the form, inputmode doesn’t change the way the browser interprets the input — it instructs the browser which keyboard to display.

The inputmode attribute has a long history but has only very recently been adopted by the two major mobile browsers: Safari for iOS and Chrome for Android. Before that, it was implemented in Firefox for Android way back in 2012, and then subsequently removed several months later (though it is still available via a flag).

Almost six years later, Chrome for Android implemented the feature — and with the recent release of iOS 12.2, Safari now supports it too.

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

DesktopChromeOperaFirefoxIEEdgeSafari665320No75NoMobile / TabletiOS SafariOpera MobileOpera MiniAndroidAndroid ChromeAndroid Firefox12.2NoNo6774No

But before we go deep into the ins and outs of the attribute, consider that the WHATWG living standard provides inputmode documentation while the W3C 5.2 spec no longer lists it in its contents, which suggests they consider it obsolete. Given that WHATWG has documented it and browsers have worked toward supporting it, we’re going to go assume WHATWG specifications are the standard.

inputmode accepts a number of values. Let’s go through them, one by one.

None <input type="text" inputmode="none" />

We’re starting here because it’s very possible we don’t want any type of keyboard on an input. Using inputmode=none will not show a keyboard at all on Chrome for Android. iOS 12.2 will still show its default alphanumeric keyboard, so specifying none could be sort of a reset for iOS in that regard. Regardless, none is intended for content that renders its own keyboard control.

Numeric <input type="text" inputmode="numeric" />

This one is probably the one of the more common inputmode values out in the wild because it’s ideal for inputs that require numbers but no letters — things like PIN entry, zip codes, credit card numbers, etc. Using the numeric value with an input of type="text" may actually make more sense than setting the input to type="number" alone because, unlike a , <code>inputmode="numeric" can be used with maxlength, minlength and pattern attributes, making it more versatile for different use cases.

The numeric value on Chrome Android (left) and iOS 12.2 (right)

I’ve often seen sites using type=tel on an input to display a numeric keyboard, and that checks out as a workaround, but isn’t semantically correct. If that bums you out, remember that inputmode supports patterns, we can add pattern="\d*" to the input for the same effect. That said, only use this if you are certain the input should only allow numeric input because Android (unlike iOS) doesn’t allow the user to change to the keyboard to use letters, which might inadvertently prevent users from submitting valid data.

Tel <input type="text" inputmode="tel" />

Entering a telephone number using a standard alphanumeric keyboard can be a pain. For one, each number on a telephone keyboard (except 1 and 0) represents three letters (e.g. 2 represents A, B and C) which are displayed with the number. The alphanumeric keyboard does not reference those letters, so decoding a telephone number containing letters (e.g. 1-800-COLLECT) takes more mental power.

The tel value on Chrome Android (left) and iOS 12.2 (right)

Using inputmode set to tel will produce a standard-looking telephone keyboard, including keys for digits 0 to 9, the pound (#) character, and the asterisk (*) character. Plus, we get those alphabetic mnemonic labels (e.g. ABC).

Decimal <input type="text" inputmode="decimal" /> The decimal value on Chrome Android (left) and iOS 12.2 (right)

An inputmode set to the decimal value results in a subtle change in iOS where the keyboard appears to be exactly the same as the tel value, but replaces the +*# key with a simple decimal (.). On the flip side, this has no effect on Android, which will simply use the numeric keyboard.

Email <input type="text" inputmode="email" />

I’m sure you (and at least someone you know) has filled out a form that asks for an email address, only to make you swap keyboards to access the @ character. It’s not life-threatening or anything, but certainly not a great user experience either.

That’s where the email value comes in. It brings the @ character into the fray, as well as the decimal (.) character.

The email value on Chrome Android (left) and iOS 12.2 (right)

This could also be a useful keyboard to show users who need to enter a Twitter username, given that@ is a core Twitter character for identifying users. However, the email address suggestions that iOS display above the keyboard may cause confusion.

Another use case could be if you have your own email validation script and don't want to use the browsers built-in email validation.

URL <input type="text" inputmode="url" /> The url value on Chrome Android (left) and iOS 12.2 (right)

The url value provides a handy shortcut for users to append TLDs (e.g. .com or .co.uk) with a single key, as well keys typically used in web addresses, like the dot (.) and forward slash (/) characters. The exact TLD displayed on the keyboard is tied to the user’s locale.

This could also be a useful keyboard to show users if your input accepts domain names (e.g. css-tricks.com) as well as full URIs (e.g. https://css-tricks.com). Use type="url" instead if your input requires validating the input.

Search <input type="text" inputmode="search" /> The search value on Chrome Android (left) and iOS 12.2 (right)

This displays a blue Go key on iOS and a green Enter key on Android, both in place of where Return. As you may have guessed by the value’s name, search is useful for search forms, providing that submission key to make a query.

If you'd like to showSearch instead of Enter on iOS and a magnifying glass icon on Android in place of the green arrow, use type=search instead.

Other things you oughta know
  • Chromium-based browsers on Android — such as Microsoft Edge, Brave and Opera — share the same inputmode behavior as Chrome.
  • I haven’t included details of keyboards on iPad for the sake of brevity. It’s mostly the same as iPhone but includes more keys. Same is true for Android tablets, save for third-party keyboards, which might be another topic worth covering.
  • The original proposed spec had the values kana and katakana for Japanese input but they were never implemented by any browser and have since been removed from the spec.
  • latin-name was also one of the values of the original spec and has since been removed. Interestingly, if it’s used now on Safari for iOS, it will display the user’s name as a suggestion above the keyboard.

    The latin-name value displays my name as an auto-fill suggestion
Demo

Oh, you want to see how all of these input modes work for yourself? Here’s a demo you can use on a device with a touchscreen keyboard to see the differences.

References

Weekly news: PWA Issue on iOS, Performance Culture, Anti-Tracking in Browsers

Css Tricks - Fri, 05/17/2019 - 4:30am

Šime posts regular content for web developers on webplatform.news. Each week, he covers timely news at the intersection of development standards and the tools that make them available on the web.

Installed PWAs cannot easily be restarted on iOS

iOS 12.2 PWAs
&#x1f501; In-App browser for external content (OAuth)
&#x1f4be; New lifecycle (No Reload)
&#x1f519;Navigation gestures
&#x1f91d;WebShare
⚠️Motion Sensors disabled; old getUserMedia removed
&#x1f44d; IntersectionObserver, ConicGradients, datalist, color picker, AbortFetchhttps://t.co/LNzq6MzqjR

— Maximiliano Firtman @ &#x1f1f1;&#x1f1f9; Vilnius (@firt) March 26, 2019

Maximiliano Firtman: On iOS, it is not possible to restart an installed PWA by closing it from the recently used apps screen and then immediately reopening it. Instead of restarting the app, iOS restores its state. This can be a problem for users if the PWA gets stuck in a broken state.

<input> with type 'file' bug on #iOS 12.2 #PWA
Open the input, put the PWA in bg by pressing home button. The input stops working. True for any input with type 'file' throughout the app. It works after a phone restart. pic.twitter.com/IfzsXy91RK

— Pankaj Nathani ⭐️ (@croozeus) April 11, 2019

After some undefined time, the saved context seems to disappear. So if you get out of the PWA, do nothing with your phone and wait some hours to go back to the PWA, it restarts from scratch.

Instilling a performance culture at The Telegraph

We've been working hard at The Telegraph to improve third-party performance. Here is an insight into our approach - https://t.co/4hhRDYaidS #webperf ⚡️

— Gareth Clubb (@digitalclubb) April 30, 2019

Gareth Clubb: At The Telegraph (a major UK newspaper), we set up a web performance working group to tackle our “organizational” performance challenges and instill a performance culture. The group meets regularly to review third-party tags and work on improving our site’s performance.

We’ve started deferring all JavaScript (including our own) using the <script defer> attribute. This change alone nearly doubled our (un-throttled) Lighthouse performance score.

Deferring our JavaScript hasn’t skewed any existing analytics and it certainly hasn’t delayed any advertising. [...] The First Ad Loaded metric improved by an average of four seconds.

We also removed 1 MB of third-party payload from our new front end. When one of our teams requests the addition of any new script, we now test the script in isolation and reject it if it degrades our metrics (first contentful paint, etc.).

When we started this process, we had a collection of very old scripts and couldn’t track the original requester. We removed those on the premise that, if they were important, people would get back in touch?—?no one did.

Microsoft plans to add tracking prevention to the Edge browser

Kyle Pflug: Microsoft has announced plans to add options for blocking trackers to the Edge browser. Malicious trackers would be blocked automatically, and the user would have the option to additionally block all potential trackers.

This would make Edge the fourth major browser with some form of built-in anti-tracking feature (two other major browsers, Opera and UC Browser, include ad blockers instead).

  1. In 2015, Firefox added Tracking Protection?—?recently renamed to Content Blocking?—?becoming the first major browser to protect users from third-party trackers (when browsing the web in private mode).
  2. Since 2017, Safari prevents cross-site tracking by default, through a feature called Intelligent Tracking Prevention (ITP). Users are prompted to allow tracking when they try to interact with third-party widgets on websites.

  3. Earlier this year, Samsung Internet added an experimental feature called Smart Anti-Tracking that denies third-party trackers access to cookies.

The post Weekly news: PWA Issue on iOS, Performance Culture, Anti-Tracking in Browsers appeared first on CSS-Tricks.

These Are The Top 6 Most Common UX Mistakes – How Many Are You Making?

Usability Geek - Thu, 05/16/2019 - 12:11pm
The user experience (UX) is all-important in the modern business sphere. The experience your target audience has from the moment they click on your website to (ideally) making a purchase creates...
Categories: Web Standards

Iterating a React Design with Styled Components

Css Tricks - Thu, 05/16/2019 - 4:29am

In a perfect world, our projects would have unlimited resources and time. Our teams would begin coding with well thought out and highly refined UX designs. There would be consensus among developers about the best way to approach styling. There’d be one or more CSS gurus on the team who could ensure that functionality and style could roll out simultaneously without it turning into a train-wreck.

I’ve actually seen this happen in large enterprise environments. It’s a beautiful thing. This article is not for those people.

On the flip side of the coin is the tiny startup that has zero funding, one or two front-end developers, and a very short timeline to demonstrate some functionality. It doesn’t have to look perfect, but it should at least render reasonably well on desktop, tablet, and mobile. This gets them to a point where it can be shown to advisors and early users; maybe even potential investors who’ve expressed an interest in the concept. Once they get some cashflow from sales and/or investment, they can get a dedicated UX designer and polish the interface.

What follows is for this latter group.

Project Kickoff Meeting

Let’s invent a company to get the ball rolling.

Solar Excursions is a small travel agency aiming to serve the near-future’s burgeoning space tourism industry.

Our tiny development team has agreed that React will be used for the UI. One of our front-end developers is big on Sass, and the other is enamored with CSS in JavaScript. But they’ll be hard pressed to knock out their initial sprint goals; there’s certainly no time for arguing about the best possible styling approach. Both coders agree the choice doesn’t matter much in the long run, as long as its consistently executed. They’re certain that implementing the styling from scratch under the gun now will incur technical debt that will have to be cleaned up later.

After some discussion, the team opts to plan for one or more "styling refactor" sprints. For now, we’ll just focus on getting something up on the screen using React-Bootstrap. That way we’ll be able to quickly build working desktop and mobile layouts without much fuss.

The less time spent on front-end styling the better, because we’ll also need the UI to hook up to the services our backend developer will be cranking out. And, as our application architecture begins to take shape, both front-enders agree it’s important that it be unit tested. They have a lot on their plate.

Based on my discussions with the Powers That Be, as a dedicated project manager, I slaved over Balsamiq for at least ten minutes to provide the team with mockups for the booking page on desktop and mobile. I assume they’ll make tablet meet in the middle and look reasonable.

Initial mockups for the Solar Excursions Trip Booking Page on desktop (left) and mobile (right). Sprint Zero: Review Meeting

Pizza all around! The team worked really hard to hit its goals, and we now have a booking page with a layout that approximates the mockups. The infrastructure for services is coming together, but there’s quite a way to go before we can connect the UI to it. In the interim, the front-enders are using a hardcoded mock data structure.

The first iteration of the page in code using react-bootstrap.

Here’s a look at our UI code so far:

This is all straightforward React. We’re using some of that Hooks hotness, but it’s probably passé to most of you by now.

The key takeaway to notice here is how four of our five application components import and use components from react-bootstrap. Only the main App component is unaffected. That’s because it just composes the top level view with our custom components.

// App.js imports import React, { useState } from "react"; import Navigation from "./Navigation"; import Page from "./Page"; // Navigation.js imports import React from "react"; import { Navbar, Dropdown, Nav } from "react-bootstrap"; // Page.js imports import React from "react"; import PosterCarousel from "./PosterCarousel"; import DestinationLayout from "./DestinationLayout"; import { Container, Row, Col } from "react-bootstrap"; // PosterCarousel.js imports import React from "react"; import { Alert, Carousel, Image } from "react-bootstrap"; // DestinationLayout.js imports import React, { useState, useEffect } from "react"; import { Button, Card, Col, Container, Dropdown, Jumbotron, ListGroup, Row, ToggleButtonGroup, ToggleButton } from "react-bootstrap";

The decision to move fast with Bootstrap has allowed us to hit our sprint goals, but we’re already accumulating technical debt. This is just four affected components, but as the application grows, it’s clear the "styling refactor" sprints that we planned for are going to become exponentially harder. And we haven’t even customized these components much. Once we have tens of components, all using Bootstrap with lots of inline styling to pretty them up, refactoring them to remove react-bootstrap dependencies will be a scary proposition indeed.

Rather than building more of the booking pipeline pages, the team decides that we’ll spend the next sprint working to isolate the react-bootstrap usage in a custom component kit since our services are still under construction. Application components will only use components from this kit. That way, when it comes time to ween ourselves from react-bootstrap, the process will be much easier. We won’t have to refactor thirty usages of the react-bootstrap Button throughout the app, we’ll just rewrite the internals of our KitButton component.

Sprint One: Review Meeting

Well, that was easy. High-fives. No change to the visual appearance of the UI, but we now have a "kit" folder that’s sibling to "components" in our React source. It has a bunch of files like KitButton.js, which basically export renamed react-bootstrap components.

An example component from our kit looks like this:

// KitButton.js import { Button, ToggleButton, ToggleButtonGroup } from "react-bootstrap"; export const KitButton = Button; export const KitToggleButton = ToggleButton; export const KitToggleButtonGroup = ToggleButtonGroup;

We wrap those all kit components up into a module like this:

// kit/index.js import { KitCard } from "./KitCard"; import { KitHero } from "./KitHero"; import { KitList } from "./KitList"; import { KitImage } from "./KitImage"; import { KitCarousel } from "./KitCarousel"; import { KitDropdown } from "./KitDropdown"; import { KitAttribution } from "./KitAttribution"; import { KitNavbar, KitNav } from "./KitNavbar"; import { KitContainer, KitRow, KitCol } from "./KitContainer"; import { KitButton, KitToggleButton, KitToggleButtonGroup } from "./KitButton"; export { KitCard, KitHero, KitList, KitImage, KitCarousel, KitDropdown, KitAttribution, KitButton, KitToggleButton, KitToggleButtonGroup, KitContainer, KitRow, KitCol, KitNavbar, KitNav };

And now our application components are completely free of react-bootstrap. Here are the imports for the affected components:

// Navigation.js imports import React from "react"; import { KitNavbar, KitNav, KitDropdown } from "../kit"; // Page.js imports import React from "react"; import PosterCarousel from "./PosterCarousel"; import DestinationLayout from "./DestinationLayout"; import { KitContainer, KitRow, KitCol } from "../kit"; // PosterCarousel.js imports import React from "react"; import { KitAttribution, KitImage, KitCarousel } from "../kit"; // DestinationLayout.js imports import React, { useState, useEffect } from "react"; import { KitCard, KitHero, KitList, KitButton, KitToggleButton, KitToggleButtonGroup, KitDropdown, KitContainer, KitRow, KitCol } from "../kit";

Here’s the front-end codebase now:

Although we’ve corralled all of the react imports into our kit components, our application components still rely a bit on the react-bootstrap implementation because the attributes we place on our kit component instances are the same as those of react-bootstrap. That constrains us when it comes to re-implementing the kit components, because we need to adhere to the same API. For instance:

// From Navigation.js <KitNavbar bg="dark" variant="dark" fixed="top">

Ideally, we wouldn’t have to add those react-bootstrap specific attributes when we instantiate our KitNavbar.

The front-enders promise to refactor those out as we go, now that we’ve identified them as problematic. And any new references to react-bootstrap components will go into our kit instead of directly into the application components.

Meanwhile, we’ve shared our mock data with the server engineer, who is working hard to build separate server environments, implement the database schema, and expose some services to us.

That gives us time to add some gloss to our UI in the next sprint — which is good because the Powers That Be would like to see separate themes for each destination. As the user browses destinations, we need to have the UI color scheme change to match the displayed travel poster. Also, we want to try and spiff up those components a bit to begin evolving our own look and feel. Once we have some money coming in, we’ll get a designer to do a complete overhaul, but hopefully we can reach a happy medium for our early users.

Sprint Two: Review Meeting

Wow! The team really pulled out all the stops this sprint. We got per-destination themes, customized components, and a lot of the lingering react-bootstrap API implementations removed from the application components.

Here’s what the desktop looks like now:

Check out the solarized theme for the red planet!

In order to pull this off, the front-enders brought in the Styled Components library. It made styling the individual kit components a breeze, as well as adding support for multiple themes.

Let’s look at a few highlights of their changes for this sprint.

First, for global things like pulling in fonts and setting the page body styles, we have a new kit component called KitGlobal.

// KitGlobal.js import { createGlobalStyle } from "styled-components"; export const KitGlobal = createGlobalStyle` body { @import url('https://fonts.googleapis.com/css?family=Orbitron:500|Nunito:600|Alegreya+Sans+SC:700'); background-color: ${props => props.theme.foreground}; overflow-x: hidden; } `;

It uses the createGlobalStyle helper to define the CSS for the body element. That imports our desired web fonts from Google, sets the background color to whatever the current theme’s "foreground" value is, and turns off overflow in the x-direction to eliminate a pesky horizontal scrollbar. We use that KitGlobal component in the render method of our App component.

Also in the App component, we import ThemeProvider from styled-components, and something called "themes" from ../theme. We use React’s useState to set the initial theme to themes.luna and React’s useEffect to call setTheme whenever the "destination" changes. The returned component is now wrapped in ThemeProvider, which is passed "theme" as a prop. Here’s the App component in its entirety.

// App.js import React, { useState, useEffect } from "react"; import { ThemeProvider } from "styled-components"; import themes from "../theme/"; import { KitGlobal } from "../kit"; import Navigation from "./Navigation"; import Page from "./Page"; export default function App(props) { const [destinationIndex, setDestinationIndex] = useState(0); const [theme, setTheme] = useState(themes.luna); const destination = props.destinations[destinationIndex]; useEffect(() => { setTheme(themes[destination.theme]); }, [destination]); return ( <ThemeProvider theme={theme}> <React.Fragment> <KitGlobal /> <Navigation {...props} destinationIndex={destinationIndex} setDestinationIndex={setDestinationIndex} /> <Page {...props} destinationIndex={destinationIndex} setDestinationIndex={setDestinationIndex} /> </React.Fragment> </ThemeProvider> ); }

KitGlobal is rendering like any other component. Nothing special there, only that the body tag is affected. ThemeProvider is using the React Context API to pass theme down to whatever components need it (which is all of them). In order to fully understand that, we also need to take a look at what a theme actually is.

To create a theme, one of our front-enders took all the travel posters and created palettes for each by extracting the prominent colors. That was fairly simple.

We used TinyEye for this.

Obviously, we weren’t going to use all the colors. The approach was mainly to dub the most used two colors foreground and background. Then we took three more colors, generally ordered from lightest to darkest as accent1, accent2, and accent3. Finally, we picked two contrasting colors to call text1 and text2. For the above destination, that looked like:

// theme/index.js (partial list) const themes = { ... mars: { background: "#a53237", foreground: "#f66f40", accent1: "#f8986d", accent2: "#9c4952", accent3: "#f66f40", text1: "#f5e5e1", text2: "#354f55" }, ... }; export default themes;

Once we have a theme for each destination, and it is being passed into all the components (including the kit components that our application components are now built from), we need to use styled-components to apply those theme colors as well as our custom visual styling, like the panel corners and "border glow."

This is a simple example where we made our KitHero component apply the theme and custom styles to the Bootstrap Jumbotron:

// KitHero.js import styled from "styled-components"; import { Jumbotron } from "react-bootstrap"; export const KitHero = styled(Jumbotron)` background-color: ${props => props.theme.accent1}; color: ${props => props.theme.text2}; border-radius: 7px 25px; border-color: ${props => props.theme.accent3}; border-style: solid; border-width: 1px; box-shadow: 0 0 1px 2px #fdb813, 0 0 3px 4px #f8986d; font-family: "Nunito", sans-serif; margin-bottom: 20px; `;

In this case, we’re good to go with what gets returned from styled-components, so we just name it KitHero and export it.

When we use it in the application, it looks like this:

// DestinationLayout.js (partial code) const renderHero = () => { return ( <KitHero> <h2>{destination.header}</h2> <p>{destination.blurb}</p> <KitButton>Book Your Trip Now!</KitButton> </KitHero> ); };

Then there are more complex cases where we want to preset some attributes on the react-bootstrap component. For instance, the KitNavbar component which we identified earlier as having a bunch of react-bootstrap attributes that we’d rather not pass from the application’s declaration of the component.

Now for a look at how that was handled:

// KitNavbar.js (partial code) import React, { Component } from "react"; import styled from "styled-components"; import { Navbar } from "react-bootstrap"; const StyledBootstrapNavbar = styled(Navbar)` background-color: ${props => props.theme.background}; box-shadow: 0 0 1px 2px #fdb813, 0 0 3px 4px #f8986d; display: flex; flex-direction: horizontal; justify-content: space-between; font-family: "Nunito", sans-serif; `; export class KitNavbar extends Component { render() { const { ...props } = this.props; return <StyledBootstrapNavbar fixed="top" {...props} />; } }

First, we create a component called StyledBootstrapNavbar using styled-components. We were able to handle some of the attributes with the CSS we passed to styled-components. But in order to continue leveraging (for now) the reliable stickiness of the component to the top of the screen while everything else is scrolled, our front-enders elected to continue using react-bootstrap’s fixed attribute. In order to do that, we had to create a KitNavbar component that rendered an instance of StyledBootstrapNavbar with the fixed=top attribute. We also passed through all the props, which includes its children.

We only have to create a separate class that renders styled-component’s work and passes props through to it if we want to explicitly set some attributes in our kit component by default. In most cases, we can just name and return styled-component’s output and use it as we did with KitHero above.

Now, when we render the KitNavbar in our application’s Navigation component, it looks like this:

// Navigation.js (partial code) return ( <KitNavbar> <KitNavbarBrand> <KitLogo /> Solar Excursions </KitNavbarBrand> {renderDestinationMenu()} </KitNavbar> );

Finally, we took our first stabs at refactoring our kit components away from react-bootstrap. The KitAttribution component is a Bootstrap Alert which, for our purposes, is little more than an ordinary div. We were able to easily refactor to remove its dependency on react-bootstrap.

This is the component as it emerged from the previous sprint:

// KitAttribution.js (using react-bootstrap) import { Alert } from "react-bootstrap"; export const KitAttribution = Alert;

This is what it looks like now:

// KitAttribution.js import styled from "styled-components"; export const KitAttribution = styled.div` text-align: center; background-color: ${props => props.theme.accent1}; color: ${props => props.theme.text2}; border-radius: 7px 25px; border-color: ${props => props.theme.accent3}; border-style: solid; border-width: 1px; box-shadow: 0 0 1px 2px #fdb813, 0 0 3px 4px #f8986d; font-family: "Alegreya Sans SC", sans-serif; > a { color: ${props => props.theme.text2}; font-family: "Nunito", sans-serif; } > a:hover { color: ${props => props.theme.background}; text-decoration-color: ${props => props.theme.accent3}; } `;

Notice how we no longer import react-bootstrap and we use styled.div as the component base. They won’t all be so easy, but it’s a process.

Here are the results of our team’s styling and theming efforts in sprint two:

View the themed page on its own here.

Conclusion

After three sprints, our team is well on its way to having a scalable component architecture in place for the UI.

  • We are moving quickly thanks to react-bootstrap, but are no longer piling up loads of technical debt as a result of it.
  • Thanks to styled-components, we were able to implement multiple themes (like how almost every app on the Internet these days sports dark and light modes). We also don’t look like an out-of-the-box Bootstrap app anymore.
  • By implementing a custom component kit that contains all references to react-bootstrap, we can refactor away from it as time permits.

Fork the final codebase on GitHub.

The post Iterating a React Design with Styled Components appeared first on CSS-Tricks.

Evergreen Googlebot

Css Tricks - Thu, 05/16/2019 - 4:28am

I've heard people say that the #1 most exciting and important thing that came out of Google I/O this year was the evergreen Googlebot:

Today, we are happy to announce that Googlebot now runs the latest Chromium rendering engine (74 at the time of this post) when rendering pages for Search. Moving forward, Googlebot will regularly update its rendering engine to ensure support for latest web platform features.

Before this, I guess I never even thought about it.

I guess part of it is that some people did already know that the old version didn't support some newfangled JavaScript stuff, and thus literally packaged their app with old JavaScript to be more SEO-friendly.

A bunch of people were apparently shipping older code simply for the sake of Googlebot, and now they don't have to. Sure, I'll call that a win.

Don't read this news as "don't worry about your JavaScript-rendered pages and SEO" though, because Google Webmasters is still telling us that pages with content that requires JavaScript to render are put into a special slower queue for both initial crawling and for updates. Not necessarily a penalty, but certainly a delay. I'm sure that's enough to make server-side rendering a priority for sites where SEO is the whole ballgame.

Direct Link to ArticlePermalink

The post Evergreen Googlebot appeared first on CSS-Tricks.

Using Jetpack to Accelerate WordPress Development

Css Tricks - Thu, 05/16/2019 - 4:25am

(This is a sponsored post.)

[Geoff:] I've built a fair number of WordPress sites in my day. It's been my go-to since the 2.x-ish days because it works for any site, big or small. That's the sort of solution and flexibility you like to have as a freelancer.

Boy, I wish I had Jetpack available in those early days.

Like WordPress itself, Jetpack is a good solution for many, many of the types of things clients are looking for from a WordPress site. I used to spend hours researching the right plugin for a specific feature, whether that was for comment filtering, asset caching, beefier search functionality, creating custom post types on the fly... you name it. All of that — and a heckuva lot more — is included in Jetpack right out of the box.

Here's what I'm talking about. A friend of mine runs a pop-up gallery here locally. She displays paintings, photographs, sculptures... basically anything super artsy from super talented locals. That includes events, socials, performances and screenings. The wild thing is that it "pops" up in different spots, based on what she's showing and what public space is available. So, you get how a website would be helpful for visitors to keep tabs on what's coming up and where things are going to take place, not to mention getting a recap on past events.

We've all made sites for friends, right? It's the kind of thing you do for free on the side. That makes it something you want to do well, but not necessarily spend a ton of time making. That's where Jetpack really helped me out in this case.

If Jetpack is new to you, it's a WordPress plugin that, as part of what it does, is bring features from WordPress.com and makes them available on your self-hosted WordPress sites.

For example, my friend really needed to showcase work. This is less of a content site and more of a visual experience, so media plays a big role. Photos, video, audio. You get it. Good thing Jetpack has a "Portfolio" custom post type at the ready.

That's a perfect start for showing things off, but my friend also needed a carousel to allow visitors to browse photos from events and artist works. This would've been something I probably would have turned to the WordPress plugin directory for in the past, or perhaps some (back then) jQuery plugin, but thankfully Jetpack had my back there, too.

While we're on the topic of media, we know that heavy image files are a recipe for slow sites. There's a ton of WordPress plugins that can help with caching, gzipping, and even lazy loading, but all that's already in Jetpack. Why go reinvent the wheel, especially on what's supposed to be a pretty quick build?

I think you catch my drift. The fact is that Jetpack is an effective way to supercharge a self-hosted WordPress site, connecting it to many of the same powerful services that you'd otherwise need to go to WordPress.com — or gobs of third-party plugins — to get. Plus, it's built by Automattic, so you know it integrates seamlessly with WordPress. No better confidence than going with something the primary maintainers of WordPress are willing to slap their name on!

Sure, we've only looked at a very simple example of how powerful Jetpack is for a small site. But don't be fooled: Jetpack is capable of handling the needs of large-scale sites as well. In fact, we love Jetpack here at CSS-Tricks because it powers so much of what you see on the site, from social sign-in and automated sharing, to downtime monitoring and site search. It's robust, dependable, and just gosh darn delightful to use.

And, hey, there's a free tier you can start using right away and it includes a generous number of features that help with security, performance, analytics, and theming... and it only goes up from there. &#x1f680;

Get Jetpack

Direct Link to ArticlePermalink

The post Using Jetpack to Accelerate WordPress Development appeared first on CSS-Tricks.

Put Wix SEO to the Test for $25K: A Battle Between Wix SEO Lovers & Haters [Sponsored]

Usability Geek - Wed, 05/15/2019 - 10:40am
Think Wix websites don’t rank well on Google? Wix says they do and they’re willing to put their money where their mouth is. Wix is recruiting two agencies to battle for the highest...
Categories: Web Standards

A Deep Dive into Native Lazy-Loading for Images and Frames

Css Tricks - Wed, 05/15/2019 - 5:04am

Today's websites are packed with heavy media assets like images and videos. Images make up around 50% of an average website's traffic. Many of them, however, are never shown to a user because they're placed way below the fold.

What’s this thing about images being lazy, you ask? Lazy-loading is something that’s been covered quite a bit here on CSS-Tricks, including a thorough guide with documentation for different approaches using JavaScript. In short, we’re talking about a mechanism that defers the network traffic necessary to load content when it’s needed — or rather when trigger the load when the content enters the viewport.

The benefit? A smaller initial page that loads faster and saves network requests for items that may not be needed if the user never gets there.

If you read through other lazy-loading guides on this or other sites, you’ll see that we’ve had to resort to different tactics to make lazy-loading work. Well, that’s about to change when lazy-loading will be available natively in HTML as a new loading attribute… at least in Chrome which will hopefully lead to wider adoption. Chrome has already merged the code for native lazy-loading and is expected to ship it in Chrome 75, which is slated to release June 4, 2019.

The pre-native approach

Until now, developers like ourselves have had to use JavaScript (whether it’s a library or something written from scratch) in order to achieve lazy-loading. Most libraries work like this:

  • The initial, server-side HTML response includes an img element without the src attribute so the browser does not load any data. Instead, the image's URL is set as another attribute in the element's data set, e.?g. data-src.
  • <img data-src="https://tiny.pictures/example1.jpg" alt="...">
  • Then, a lazy-loading library is loaded and executed.
  • <script src="LazyLoadingLibrary.js"></script> <script>LazyLoadingLibrary.run()</script>
  • That keeps track of the user's scrolling behavior and tells the browser to load the image when it is about to be scrolled into view. It does that by copying the data-src attribute's value to the previously empty src attribute.
  • <img src="https://tiny.pictures/example1.jpg" data-src="https://tiny.pictures/example1.jpg" alt="...">

This has worked for a pretty long time now and gets the job done. But it’s not ideal for good reasons.

The obvious problem with this approach is the length of the critical path for displaying the website. It consists of three steps, which have to be carried out in sequence (after each other):

  1. Load the initial HTML response
  2. Load the lazy-loading library
  3. Load the image file

If this technique is used for images above the fold the website will flicker during loading because it is first painted without the image (after step 1 or 2, depending on if the script uses defer or async) and then — after having been loaded — include the image. It will also be perceived as loading slowly.

In addition, the lazy-loading library itself puts an extra weight on the website's bandwidth and CPU requirements. And let’s not forget that a JavaScript approach won't work for people who have JavaScript disabled (although we shouldn't really care about them in 2019, should we?).

Oh, and what about sites that rely on RSS to distribute content, like CSS-Tricks? The initial image-less render means there are no images in the RSS version of content as well.

And so on.

Native lazy-loading to the rescue!

As we noted at the start, Chromium and Google Chrome will ship a native lazy-loading mechanism in the form of a new loading attribute, starting in Chrome 75. We’ll go over the attribute and its values in just a bit, but let’s first get it working in our browsers so we can check it out together.

Enable native lazy-loading

Until Chrome 75 is officially released, we have Chrome Canary and can enable lazy-loading manually by switching two flags.

  1. Open chrome://flags in Chromium or Chrome Canary.
  2. Search for lazy.
  3. Enable both the "Enable lazy image loading" and the "Enable lazy frame loading" flag.
  4. Restart the browser with the button in the lower right corner of the screen.
Native lazy-loading flags in Google Chrome

You can check if the feature is properly enabled by opening your JavaScript console (F12). You should see the following warning:

[Intervention] Images loaded lazily and replaced with placeholders. Load events are deferred."

All set? Now we get to dig into the loading attribute.

The loading attribute

Both the img and the iframe elements will accept the loading attribute. It's important to note that its values will not be taken as a strict order by the browser but rather as a hint to help the browser make its own decision whether or not to load the image or frame lazily.

The attribute can have three values which are explained below. Next to the images, you'll find tables listing your individual resource loading timings for this page load. Range response refers to a kind of partial pre-flight request made to determine the image's dimensions (see How it works) for details). If this column is filled, the browser made a successful range request.

Please note the startTime column, which states the time image loading was deferred after the DOM had been parsed. You might have to perform a hard reload (CTRL + Shift + R) to re-trigger range requests.

The auto (or unset) value <img src="auto-cat.jpg" loading="auto" alt="..."> <img src="auto-cat.jpg" alt="..."> <iframe src="https://css-tricks.com/" loading="auto"></iframe> <iframe src="https://css-tricks.com/"></iframe> Auto cat loaded automatically

Setting the loading attribute to auto (or simply leaving the value blank, as in loading="") lets the browser decide whether or not to lazy-load an image. It takes many things into consideration to make that decision, like the platform, whether Data Saver mode is enabled, network conditions, image size, image vs. iframe, the CSS display property, among others. (See How it works) for info about why all this is important.)

The eager value <img src="auto-cat.jpg" loading="eager" alt="..."> <iframe src="https://css-tricks.com/" loading="eager"></iframe> Eager cat loaded eagerly

The eager value provides a hint to the browser that an image should be loaded immediately. If loading was already deferred (e.?g. because it had been set to lazy and was then changed to eager by JavaScript), the browser should start loading the image immediately.

The lazy value <img src="auto-cat.jpg" loading="lazy" alt="..."> <iframe src="https://css-tricks.com/" loading="lazy"></iframe> Lazy cat loaded lazily

The lazy value provides a hints to the browser that an image should be lazy-loaded. It's up to the browser to interpret what exactly this means, but the explainer document states that it should start loading when the user scrolls "near" the image such that it is probably loaded once it actually comes into view.

How the loading attribute works

In contrast to JavaScript lazy-loading libraries, native lazy-loading uses a kind of pre-flight request to get the first 2048?bytes of the image file. Using these, the browser tries to determine the image's dimensions in order to insert an invisible placeholder for the full image and prevent content from jumping during loading.

The image's load event is fired as soon as the full image is loaded, be it after the first request (for images smaller than 2?KB) or after the second one. Please note that the load event may never be fired for certain images because the second request is never made.

In the future, browsers might make twice as many image requests as there would be under the current proposal. First the range request, then the full request. Make sure your servers support the HTTP Range: 0-2047 header and respond with status code 206 (Partial Content) to prevent them from delivering the full image twice.

Due to the higher number of subsequent requests made by the same user, web server support for the HTTP/2 protocol will become more important.

Let’s talk about deferred content. Chrome's rendering engine Blink uses heuristics to determine which content should be deferred and for how long to defer it. You can find a comprehensive list of requirements in Scott Little's design documentation. This is a short breakdown of what will be deferred:

  • Images and frames on all platforms which have loading="lazy" set
  • Images on Chrome for Android with Data Saver enabled and that satisfy all of the following:
    • loading="auto" or unset
    • no width and height attributes smaller than 10px
    • not created programmatically in JavaScript
  • Frames which satisfy all of the following:
    • loading="auto" or unset
    • is from a third-party (different domain or protocol than the embedding page)
    • larger than 4 pixels in height and width (to prevent deferring tiny tracking frames)
    • not marked as display: none or visibility: hidden (again, to prevent deferring tracking frames)
    • not positioned off-screen using negative x or y coordinates
Responsive images with srcset

Native lazy-loading also works with responsive img elements using the srcset attribute. This attribute offers a list of image file candidates to the browser. Based on the user's screen size, display pixel ratio, network conditions, etc., the browser will choose the optimal image candidate for the occasion. Image optimization CDNs like tiny.pictures are able to provide all image candidates in real-time without any back end development necessary.

<img src="https://demo.tiny.pictures/native-lazy-loading/lazy-cat.jpg" srcset="https://demo.tiny.pictures/native-lazy-loading/lazy-cat.jpg?width=400 400w, https://demo.tiny.pictures/native-lazy-loading/lazy-cat.jpg?width=800 800w" loading="lazy" alt="..."> Browser support

At the time of this writing, no browser supports native-loading by default. However, Chrome will enable the feature, as we’ve covered, starting in Chrome 75. No other browser vendor has announced support so far. (Edge being a kind of exception because it will soon make the switch to Chromium.)

You can detect the feature with a few lines of JavaScript:

if ("loading" in HTMLImageElement.prototype) { // Support. } else { // No support. You might want to dynamically import a lazy-loading library here (see below). }

See the Pen
Native lazy-loading browser support
by Erk Struwe (@erkstruwe)
on CodePen.

Automatic fallback to JavaScript solution with low-quality image placeholder

One very cool feature of most JavaScript-based lazy-loading libraries is the low-quality image placeholder (LQIP). Basically, it leverages the idea that browsers load (or perhaps I should say used to load) the src of an img element immediately, even if it gets later replaced by another URL. This way, it’s possible to load a tiny file size, low-quality image file on page load and later replace it with a full-sized version.

We can now use this to mimic the native lazy-loading’s 2 KB range requests in browsers that do not support this feature in order to achieve the same result, namely a placeholder with the actual image dimensions and a tiny file size.

See the Pen
Native lazy-loading with JavaScript library fallback and low-quality image placeholder
by Erk Struwe (@erkstruwe)
on CodePen.

Conclusion

I'm really excited about this feature. And frankly, I'm still wondering why it hasn't got much more attention until now, given the fact that its release is imminent and the impact on global internet traffic will be remarkable, even if only small parts of the heuristics are changed.

Think about it: After a gradual roll-out for the different Chrome platforms and with auto being the default setting, the world's most popular browser will soon lazy-load below-the-fold images and frames by default. Not only will the traffic amount of many badly-written websites drop significantly, but web servers will be hammered with tiny requests for image dimension detection.

And then there's tracking: Assuming many unsuspecting tracking pixels and frames will be prevented from being loaded, the analytics and affiliate industry will have to act. We can only hope they don't panic and add loading="eager" to every single image, rendering this great feature useless for their users. They should rather change their code to be recognized as tracking pixels by the heuristics described above.

Web developers, analytics and operations managers should check their website's behavior with this feature and their servers' support for Range requests and HTTP/2 immediately.

Image optimization CDNs could help out in case there are any issues to be expected or if you’d like to take image delivery optimization to the max (including automatic WebP support, low-quality image placeholders, and much more). Read more about tiny.pictures!

References

The post A Deep Dive into Native Lazy-Loading for Images and Frames appeared first on CSS-Tricks.

A Better Approach for Using Purgecss with Tailwind

Css Tricks - Wed, 05/15/2019 - 4:29am

Greg Kohn looks at how to use Purgecss — a tool that helps remove unused styles — and Tailwind — a utility-based CSS framework — and why we might want to pair these tools together:

Tailwind, by intention, is aiming to equip you with an arsenal of utility classes by generating more than you need. There are some best practices which will help keep this overall build size down, like limiting your colors and breakpoints or turning off the modules by default before adding them as necessary. Still, you’ll inevitably generate classes that go unused. And honestly, approaching your configuration with an unrelenting miserly attitude will slow you down and make development less fun. By leaning on Purgecss, there’s no worry that the CSS your users download will only include classes that are ultimately needed.

I’ve never used Tailwind or Purgecss, but I reckon the latter could be particularly useful if you have a giant old codebase and you don’t have the resources to refactor things just yet. I guess my only concern with introducing a tool like that is it could encourage folks to not refactor large and problematic areas in their styles – taking the safest route with this tool instead.

For more info about Tailwind, though, Ben Tinsley wrote a great post a while back about how to get started and Nick Basile showed us how to style a form with Tailwind.

Direct Link to ArticlePermalink

The post A Better Approach for Using Purgecss with Tailwind appeared first on CSS-Tricks.

UI Patterns For Navigation That Makes Good UX Sense

Usability Geek - Tue, 05/14/2019 - 12:36pm
Mobile Apps are born from ideas, substantiated by a purpose. As entrepreneurs, designers, or developers, our focus lies in giving users a wholesome experience besides driving them through a smooth...
Categories: Web Standards

Integrating Third-Party Animation Libraries to a Project

Css Tricks - Tue, 05/14/2019 - 4:28am

Creating CSS-based animations and transitions can be a challenge. They can be complex and time-consuming. Need to move forward with a project with little time to tweak the perfect transition? Consider a third-party CSS animation library with ready-to-go animations waiting to be used. Yet, you might be thinking: What are they? What do they offer? How do I use them?

Well, let’s find out.

A (sort of) brief history of :hover

Once there was a time that the concept of a hover state was a trivial example of what is offered today. In fact, the idea of having a reaction to the cursor passing on top of an element was more-or-less nonexistent. Different ways to provide this feature were proposed and implemented. This small feature, in a way, opened the door to the idea of CSS being capable of animations for elements on the page. Over time, the increasing complexity possible with these features have led to CSS animation libraries.

Macromedia’s Dreamweaver was introduced in December 1997 and offered what was a simple feature, an image swap on hover. This feature was implemented with a JavaScript function that would be embedded in the HTML by the editor. This function was named MM_swapImage() and has become a bit of web design folklore. It was an easy script to use, even outside of Dreamweaver, and it’s popularity has resulted in it still being in use even today. In my initial research for this article, I found a question pertaining to this function from 2018 on Adobe’s Dreamweaver (Adobe acquired Macromedia in 2005) help forum.

The JavaScript function would swap an image with another image through changing the src attribute based on mouseover and mouseout events. When implemented, it looked something like this:

<a href="#" onMouseOut="MM_swapImgRestore()" onMouseOver="MM_swapImage('ImageName','','newImage.jpg',1)"> <img src="originalImage.jpg" name="ImageName" width="100" height="100" border="0"> </a>

By today’s standards, it would be fairly easy to accomplish this with JavaScript and many of us could practically do this in our sleep. But consider that JavaScript was still this new scripting language at the time (created in 1995) and sometimes looked and behaved differently from browser to browser. Creating cross-browser JavaScript was not always an easy task and not everyone creating web pages even wrote JavaScript. (Though that has certainly changed.) Dreamweaver offered this functionality through a menu in the editor and the web designer didn’t even need to write the JavaScript. It was based around a set of "behaviors" that could be selected from a list of different options. These options could be filtered by a set of targeted browsers; 3.0 browsers, 4.0 browsers, IE 3.0, IE 4.0, Netscape 3.0, Netscape 4.0. Ah, the good old days.

Choosing Behaviors based on browser versions, circa 1997. The Swap Image Behaviors panel in Macromedia Dreamweaver 1.2a

About a year after Dreamweaver was first released, the CSS2 specification from W3C mentioned :hover in a working draft dated January 1998. It was specifically mentioned in terms of anchor links, but the language suggests it could have possibly been applied to other elements. For most purposes it would seem this pseudo selector would be the beginning of an easy alternative to MM_swapImage(), since background-image was in the same draft. Although browser support was an issue as it took years before enough browsers properly supported CSS2 to make it a viable option for many web designers. There was finally a W3C recommendation of CSS2.1, this could be considered to be the basis of "modern" CSS as we know it, which was published in June 2011.

In the middle of all this, jQuery came along in 2006. Thankfully, jQuery went a long way in simplifying JavaScript among the different browsers. One thing of interest for our story, the first version of jQuery offered the animate() method. With this method, you could animate CSS properties on any element at any time; not just on hover. By its sheer popularity, this method exposed the need for a more robust CSS solution baked into the browser — a solution that wouldn’t require a JavaScript library that was not always very performant due to browser limitations.

The :hover pseudo-class only offered a hard swap from one state to another with no support for a smooth transition. Nor could it animate changes in elements outside of something as basic as hovering over an element. jQuery’s animate() method offered those features. It paved the way and there was no going back. As things go in the dynamic world of web development, a working draft for solving this was well underway before the recommendation of CSS2.1 was published. The first working draft for CSS Transitions Module Level 3 was first published by the W3C in March 2009. The first working draft for CSS Animations Module Level 3 was published at roughly the same time. Both of these CSS modules are still in a working draft status as of October 2018, but of course, we are already making heavy use of them

So, what first started as a JavaScript function provided by a third-party, just for a simple hover state, has led to transitions and animations in CSS that allow for elaborate and complex animations — complexity that many developers wouldn’t necessarily wish to consider as they need to move quickly on new projects. We have gone full circle; today many third-party CSS animation libraries have been created to offset this complexity.

Three different types of third-party animation libraries

We are in this new world capable of powerful, exciting, and complex animations in our web pages and apps. Several different ideas have come to the forefront on how to approach these new tasks. It’s not that one approach is better than any other; indeed, there is a good bit of overlap in each. The difference is more about how we implement and write code for them. Some are full-blown JavaScript-only libraries while others are CSS-only collections.

JavaScript libraries

Libraries that operate solely through JavaScript often offer capabilities beyond what common CSS animations provide. Usually, there is overlap as the libraries may actually use CSS features as part of their engine, but that would be abstracted away in favor of the API. Examples of such libraries are Greensock and Anime.js. You can see the extent of what they offer by looking at the demos they provide (Greensock has a nice collection over on CodePen). They’re mostly intended for highly complex animations, but can be useful for more basic animations as well.

JavaScript and CSS libraries

There are third-party libraries that primarily include CSS classes but provide some JavaScript for easy use of the classes in your projects. One library, Micron.js, provides both a JavaScript API and data attributes that can be used on elements. This type of library allows for easy use of pre-built animations that you can just select from. Another library, Motion UI, is intended to be used with a JavaScript framework. Although, it also works on a similar notion of a mixture of a JavaScript API, pre-built classes, and data attributes. These types of libraries provide pre-built animations and an easy way to wire them up.

CSS libraries

The third kind of library is CSS-only. Typically, this is just a CSS file that you load via a link tag in your HTML. You then apply and remove specific CSS classes to make use of the provided animations. Two examples of this type of library are Animate.css and Animista. That said, there are even major differences between these two particular libraries. Animate.css is a total CSS package while Animista provides a slick interface to choose the animations you want with provided code. These libraries are often easy to implement but you have to write code to make use of them. These are the type of libraries this article will focus on.

Three different types of CSS animations

Yes, there’s a pattern; the rule of threes is everywhere, after all.

In most cases, there are three types of animations to consider when making use of third-party libraries. Each type suits a different purpose and has different ways to make use of them.

Hover animations

These animations are intended to be involved in some sort of hover state. They’re often used with buttons, but another possibility is using them to highlight sections the cursor happens to be on. They can also be used for focus states.

Attention animations

These animations are intended to be used on elements that are normally outside of the visual center of the person viewing the page. An animation is applied to a section of the display that needs attention. Such animations could be subtle in nature for things that need eventual attention but not dire in nature. They could also be highly distracting for when immediate attention is required.

Transition animations

These animations are often intended to have an element replace another in the view, but can be used for one element as well. These will usually include an animation for "leaving" the view and mirror animation for "entering" the view. Think of fading out and fading in. This is commonly needed in single page apps as one section of data would transition to another set of data, for example.

So, let’s go over examples of each of these type of animations and how one might use them.

Let’s hover it up!

Some libraries may already be set for hover effects, while some have hover states as their main purpose. One such library is Hover.css, which is a drop-in solution that provides a nice range of hover effects applied via class names. Sometimes, though, we want to make use of an animation in a library that doesn’t directly support the :hover pseudo-class because that might conflict with global styles.

For this example, I shall use the tada animation that Animate.css provides. It’s intended more as an attention seeker, but it will nicely suffice for this example. If you were to look through the CSS of the library, you’ll find that there’s no :hover pseudo-class to be found. So, we’ll have to make it work in that manner on our own.

The tada class by itself is simply this:

.tada { animation-name: tada; }

A low-lift approach to make this react to a hover state is to make our own local copy of the class, but extend it just a bit. Normally, Animate.css is a drop-in solution, so we won’t necessarily have the option to edit the original CSS file; although you could have your own local copy of the file if you wish. Therefore, we only create the code we require to be different and let the library handle the rest.

.tada-hover:hover { animation-name: tada; }

We probably shouldn’t override the original class name in case we actually want to use it elsewhere. So, instead, we make a variation that we can place the :hover pseudo-class on the selector. Now we just use the library’s required animated class along with our custom tada-hover class to an element and it will play that animation on hover.

If you wouldn’t want to create a custom class in this way, but prefer a JavaScript solution instead, there’s a relatively easy way to handle that. Oddly enough, it’s a similar method to the MM_imageSwap() method from Dreamweaver we discussed earlier.

// Let's select elements with ID #js_example var js_example = document.querySelector('#js_example'); // When elements with ID #js_example are hovered... js_example.addEventListener('mouseover', function () { // ...let's add two classes to the element: animated and tada... this.classList.add('animated', 'tada'); }); // ...then remove those classes when the mouse is not on the element. js_example.addEventListener('mouseout', function () { this.classList.remove('animated', 'tada'); });

There are actually multiple ways to handle this, depending on the context. Here, we create some event listeners to wait for the mouse-over and mouse-out events. These listeners then apply and remove the library’s animated and tada classes as needed. As you can see, extending a third-party library just a bit to suit our needs can be accomplished in relatively easy fashion.

Can I please have your attention?

Another type of animation that third-party libraries can assist with are attention seekers. These animations are useful for when you wish to draw attention to an element or section of the page. Some examples of this could be notifications or unfilled required form inputs. These animations can be subtle or direct. Subtle for when something needs eventual attention but does not need to be resolved immediately. Direct for when something needs resolution now.

Some libraries have such animations as part of the whole package, while some are built specifically for this purpose. Both Animate.css and Animista have attention seeking animations, but they are not the main purpose for those libraries. An example of a library built for this purpose would be CSShake. Which library to use depends on the needs of the project and how much time you wish to invest in implementing them. For example, CSShake is ready to go with little trouble on your part — simply apply classes as needed. Although, if you were already using a library such as Animate.css, then you’re likely not going to want to introduce a second library (for performance, reliance on dependencies, and such).

So, a library such as Animate.css can be used but needs a little more setup. The library’s GitHub page has examples of how to go about doing this. Depending on the needs of a project, implementing these animations as attention seekers is rather straightforward.

For a subtle type of animation, we could have one that just repeats a set number of times and stops. This usually involves adding the library’s classes, applying an animation iteration property to CSS, and waiting for the animation end event to clear the library’s classes.

Here’s a simple example that follows the same pattern we looked at earlier for hover states:

var pulse = document.querySelector('#pulse'); function playPulse () { pulse.classList.add('animated', 'pulse'); } pulse.addEventListener('animationend', function () { pulse.classList.remove('animated', 'pulse'); }); playPulse();

The library classes are applied when the playPulse function is called. There’s an event listener for the animationend event that will remove the library’s classes. Normally, this would only play once, but you might want to repeat multiple times before stopping. Animate.css doesn’t provide a class for this, but it’s easy enough to apply a CSS property for our element to handle this.

#pulse { animation-iteration-count: 3; /* Stop after three times */ }

This way, the animation will play three times before stopping. If we needed to stop the animation sooner, we can manually remove the library classes outside of the animationend function. The library’s documentation actually provides an example of a reusable function for applying the classes that removes them after the animation; very similar to the above code. It would even be rather easy to extend it to apply the iteration count to the element.

For a more direct approach, let’s say an infinite animation that won’t stop until after some sort of user interaction takes place. Let’s pretend that clicking the element is what starts the animation and clicking again stops it. Keep in mind that however you wish to start and stop the animation is up to you.

var bounce = document.querySelector('#bounce'); bounce.addEventListener('click', function () { if (!bounce.classList.contains('animated')) { bounce.classList.add('animated', 'bounce', 'infinite'); } else { bounce.classList.remove('animated', 'bounce', 'infinite'); } });

Simple enough. Clicking the element tests if the library’s "animated" class has been applied. If it has not, we apply the library classes so it starts the animation. If it has the classes, we remove them to stop the animation. Notice that infinite class on the end of the classList. Thankfully, Animate.css provides this for us out-of-the-box. If your library of choice doesn’t offer such a class, then this is what you need in your CSS:

#bounce { animation-iteration-count: infinite; }

Here’s a demo showing how this code behaves:

See the Pen
3rd Party Animation Libraries: Attention Seekers
by Travis Almand (@talmand)
on CodePen.

Moving stuff out of the way

When researching for this article, I found that transitions (not to be confused with CSS transitions) are easily the most common type of animations in the third-party libraries. These are simple animations that are built to allow an element to enter or leave the page. A very common pattern seen in modern Single Page Applications is to have one element leave the page while another replaces it by entering the page. Think of the first element fading out and the second fading in. This could be replacing old data with new data, moving to the next panel in a sequence, or moving from one page to another with a router. Both Sarah Drasner and Georgy Marchuk have excellent examples of these types of transitions.

For the most part, animation libraries will not provide the means to remove and add elements during the transition animations. The libraries that provide additional JavaScript may actually have this functionality, but since most do not, we’ll discuss how to handle this functionality now.

Inserting a single element

For this example, we’ll again use Animate.css as our library. In this case, I’ll be using the fadeInDown animation.

Now, please keep in mind there are many ways to handle inserting an element into the DOM and I don’t wish to cover them here. I’ll just be showing how to leverage an animation to make the insertion nicer and more natural than the element simply popping into view. For Animate.css (and likely many other libraries), inserting an element with the animation is quite easy.

let insertElement = document.createElement('div'); insertElement.innerText = 'this div is inserted'; insertElement.classList.add('animated', 'fadeInDown'); insertElement.addEventListener('animationend', function () { this.classList.remove('animated', 'fadeInDown'); }); document.body.append(insertElement);

However you decide to create the element doesn’t much matter; you just need to be sure the needed classes are already applied before inserting the element. Then it’ll nicely animate into place. I also included an event listener for the animationend event that removes the classes. As usual, there are several ways to go about doing this and this is likely the most direct way to handle it. The reason for removing the classes is to make it easier to reverse the process if we wish. We wouldn’t want the entering animation competing with a leaving animation.

Removing a single element

Removing a single element is sort of similar to inserting an element. The element already exists, so we just apply the desired animation classes. Then at the animationend event we remove the element from the DOM. In this example, we’ll use the fadeOutDown animation from Animate.css because it works nicely with the fadeInDown animation.

let removeElement = document.querySelector('#removeElement'); removeElement.addEventListener('animationend', function () { this.remove(); }); removeElement.classList.add('animated', 'fadeOutDown');

As you can see, we target the element, add the classes, and remove the element at the end of the animation.

An issue with all this is that with inserting and removing elements this way will cause the other elements on the page to jump around to adjust. You’ll have to account for that in some way, most likely with CSS and the layout of the page to keep a constant space for the elements.

Get out of my way, I’m coming through!

Now we are going to swap two elements, one leaving while another enters. There are several ways of handling this, but I’ll provide an example that’s essentially combining the previous two examples.

See the Pen
3rd Party Animation Libraries: Transitioning Two Elements
by Travis Almand (@talmand)
on CodePen.

I’ll go over the JavaScript in parts to explain how it works. First, we cache a reference to a button and the container for the two elements. Then, we create two boxes that’ll be swapped inside the container.

let button = document.querySelector('button'); let container = document.querySelector('.container'); let box1 = document.createElement('div'); let box2 = document.createElement('div');

I have a generic function for removing the animation classes for each animationEnd event.

let removeClasses = function () { box1.classList.remove('animated', 'fadeOutRight', 'fadeInLeft'); box2.classList.remove('animated', 'fadeOutRight', 'fadeInLeft'); }

The next function is the bulk of the swapping functionality. First, we determine the current box being displayed. Based on that, we can deduce the leaving and entering elements. The leaving element gets the event listener that called the switchElements function removed first so we don’t find ourselves in an animation loop. Then, we remove the leaving element from the container since its animation has finished. Next, we add the animation classes to the entering element and append it to the container so it’ll animate into place.

let switchElements = function () { let currentElement = document.querySelector('.container .box'); let leaveElement = currentElement.classList.contains('box1') ? box1 : box2; let enterElement = leaveElement === box1 ? box2 : box1; leaveElement.removeEventListener('animationend', switchElements); leaveElement.remove(); enterElement.classList.add('animated', 'fadeInLeft'); container.append(enterElement); }

We need to do some general setup for the two boxes. Plus, we append the first box to the container.

box1.classList.add('box', 'box1'); box1.addEventListener('animationend', removeClasses); box2.classList.add('box', 'box2'); box2.addEventListener('animationend', removeClasses); container.appendChild(box1);

Finally, we have a click event listener for our button that does the toggling. How these sequences of events are started is technically up to you. For this example, I decided on a simple button click. I figure out which box is currently being displayed, which will be leaving, to apply the appropriate classes to make it animate out. Then I apply an event listener for the animationEnd event that calls the switchElements function shown above that handles the actual swap.

button.addEventListener('click', function () { let currentElement = document.querySelector('.container .box'); if (currentElement.classList.contains('box1')) { box1.classList.add('animated', 'fadeOutRight'); box1.addEventListener('animationend', switchElements); } else { box2.classList.add('animated', 'fadeOutRight'); box2.addEventListener('animationend', switchElements); } }

One obvious issue with this example is that it is extremely hard-coded for this one situation. Although, it can be easily extended and adjusted for different situations. So, the example is useful in terms of understanding one way of handling such a task. Thankfully, some animation libraries, like MotionUI, provide some JavaScript to help with element transitions. Another thing to consider is that some JavaScript frameworks, such as VueJS have functionality to assist with animating element transitions.

I have also created another example that provides a more flexible system. It consists of a container that stores references to leave and enter animations with data attributes. The container holds two elements that will switch places on command. The way this example is built is that the animations are easily changed in the data attributes via JavaScript. I also have two containers in the demo; one using Animate.css and the other using Animista for animations. It’s a large example, so I won’t examine code here; but it is heavily commented, so take a look if it is of interest.

See the Pen
3rd Party Animation Libraries: Custom Transition Example
by Travis Almand (@talmand)
on CodePen.

Take a moment to consider...

Does everyone actually want to see all these animations? Some people could consider our animations over-the-top and unnecessary, but for some, they can actually cause problems. Some time ago, WebKit introduced the prefers-reduced-motion media query to assist with possible Vestibular Spectrum Disorder issues. Eric Bailey also posted a nice introduction to the media query, as well as a follow-up with considerations for best practices. Definitely read these.

So, does your animation library of choice support the prefers-reduced-motion? If the documentation doesn’t say that it does, then you may have to assume it does not. Although, it is rather easy to check the code of the library to see if there is anything for the media query. For instance, Animate.css has it in the _base.scss partial file.

@media (print), (prefers-reduced-motion) { .animated { animation: unset !important; transition: none !important; } }

This bit of code also provides an excellent example of how to do this for yourself if the library doesn’t support it. If the library has a common class it uses — like Animate.css uses "animated" — then you can just target that class. If it does not support such a class then you’ll have to target the actual animation class or create your own custom class for that purpose.

.scale-up-center { animation: scale-up-center 0.4s cubic-bezier(0.390, 0.575, 0.565, 1.000) both; } @keyframes scale-up-center { 0% { transform: scale(0.5); } 100% { transform: scale(1); } } @media (print), (prefers-reduced-motion) { .scale-up-center { animation: unset !important; transition: none !important; } }

As you can see, I just used the example as provided by Animate.css and targeted the animation class from Animista. Keep in mind that you’ll have to repeat this for every animation class you choose to use from the library. Although, in Eric’s follow-up piece, he suggests treating all animations as progressive enhancement and that could be one way to both reduce code and make a more accessible user experience.

Let a framework do the heavy lifting for you

In many ways, the various frameworks such as React and Vue can make using third-party CSS animation easier than with vanilla JavaScript, mainly because you don’t have to wire up the class swaps or animationend events manually. You can leverage the functionality the frameworks already provide. The beauty of using frameworks is that they also provide several different ways of handling these animations depending on the needs of the project. The examples below is only a small example of options.

Hover effects

For hover effects, I would suggest setting them up with CSS (as I suggested above) as the better way to go. If you really need a JavaScript solution in a framework, such as Vue, it would be something like this:

<button @mouseover="over($event, 'tada')" @mouseleave="leave($event, 'tada')"> tada </button> methods: { over: function(e, type) { e.target.classList.add('animated', type); }, leave: function (e, type) { e.target.classList.remove('animated', type); } }

Not really that much different than the vanilla JavaScript solution above. Also, as before, there are many ways of handling this.

Attention seekers

Setting up the attention seekers is actually even easier. In this case, we’re just applying the classes we require, again, using Vue as an example:

<div :class="{animated: isPulse, pulse: isPulse}">pulse</div> <div :class="[{animated: isBounce, bounce: isBounce}, 'infinite']">bounce</div>

In the pulse example, whenever the boolean isPulse is true, the two classes are applied. In the bounce example, whenever the boolean isBounce is true the animated and bounce classes are applied. The infinite class is applied regardless so we can have our never-ending bounce until the isBounce boolean goes back to false.

Transitions

Thankfully, Vue’s transition component provides an easy way to use third-party animation classes with custom transition classes. Other libraries, such as React, could offer similar features or add-ons. To make use of the animation classes in Vue, we just implement them in the transition component.

<transition enter-active-class="animated fadeInDown" leave-active-class="animated fadeOutDown" mode="out-in" > <div v-if="toggle" key="if">if example</div> <div v-else key="else">else example</div> </transition>

Using Animate.css, we merely apply the necessary classes. For enter-active, we apply the required animated class along with fadeInDown. For leave-active, we apply the required animated class along with fadeOutDown. During the transition sequence, these classes are inserted at the appropriate times. Vue handles the inserting and removing of the classes for us.

For a more complex example of using third-party animation libraries in a JavaScript framework, explore this project:

See the Pen
KLKdJy
by Travis Almand (@talmand)
on CodePen.

Join the party!

This is a small taste of the possibilities that await your project as there are many, many third-party CSS animation libraries out there to explore. Some are thorough, eccentric, specific, obnoxious, or just straight-forward. There are libraries for complex JavaScript animations such as Greensock or Anime.js. There are even libraries that will target the characters in an element.

Hopefully all this will inspire you to play with these libraries on the way to creating your own CSS animations.

The post Integrating Third-Party Animation Libraries to a Project appeared first on CSS-Tricks.

Google Fonts is Adding font-display

Css Tricks - Tue, 05/14/2019 - 4:20am

Google announced at I/O that their font service will now support the font-display property which resolves a number of web performance issues. If you're hearing cries of joy, that's probably Chris as he punches the air in celebration. He's wanted this feature for some time and suggests that all @font-face blocks ought to consider using the property.

Zach Leatherman has the lowdown:

This is big news—it means developers now have more control over Google Fonts web font loading behavior. We can enforce instant rendering of fallback text (when using font-display: swap) rather than relying on the browser default behavior of invisible text for up to 3 seconds while the web font request is in-flight.

It’s also a bit of trailblazing, too. To my knowledge, this is the first web font host that’s shipping support for this very important font-display feature.

Yes, a big deal indeed! You may recall that font-display instructs the browser how (and kinda when) to load fonts. That makes it a possible weapon to fight fight FOUT and FOIT issues. Chris has mentioned how he likes the optional value for that exact reason.

@font-face { font-family: "Open Sans Regular"; src: url("..."); font-display: optional; }

Oh and this is a good time to remind everyone of Monica Dinculescu’s font-display demo where she explores all the various font-display values and how they work in practice. It’s super nifty and worth checking out.

Direct Link to ArticlePermalink

The post Google Fonts is Adding font-display appeared first on CSS-Tricks.

Change Color of SVG on Hover

Css Tricks - Mon, 05/13/2019 - 4:44am

There are a lot of different ways to use SVG. Depending on which way, the tactic for recoloring that SVG in different states or conditions — :hover, :active, :focus, class name change, etc. — is different.

Let's look at the ways.

Inline SVG

Inline SVG is my favorite way to use SVG anyway, in part because of how easy it is to access and style the SVG.

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

If you're used to working with icon fonts, one thing you might enjoy about them is how easy it is to change the color. You're largely limited to a single color with icon fonts in a way that SVG isn't, but still, it is appealingly easy to change that single color with color. Using inline SVG allows you to set the fill, which cascades to all the elements within the SVG, or you can fill each element separately if needed.

SVG Symbol / Use

There is such thing as an SVG sprite, which is a group of SVGs turned into <symbol> elements such that any given icon can be referenced easily with a <use> element.

See the Pen
Use SVG Hovers
by Chris Coyier (@chriscoyier)
on CodePen.

You can still set the fill color from outside CSS rather easily this way, but there are caveats.

  • The internal SVG elements (like the <path>) can have no fill themselves. This allows the fill set from the parent SVG to cascade into the Shadow DOM created by <use>. As soon as you have something like <path fill="blue" ... /> in the <symbol>, you've lost outside CSS control.
  • Likewise, the fill of individual elements cannot be controlled within the SVG like you could with inline SVG. This means you're pretty firmly in single-color territory. That covers most use cases anyway, but still, a limitation nonetheless.
SVG background images

SVG can be set as a background image just like PNG, JPG, or whatever other graphics format. At this point, you've sort of given up on being able to change the fill. One possibility, which I'd argue isn't a particularly good one, is to have two versions of every icon, in the respective colors, and swap between them:

See the Pen
Background SVG Hovers
by Chris Coyier (@chriscoyier)
on CodePen.

I don't blame you if you'd rather not swap sources, so another possibility is to get gnarly with filters.

See the Pen
Background SVG Hovers with Filters
by Chris Coyier (@chriscoyier)
on CodePen.

Trying to finagle the right filters to get the color right is tricky stuff. Fortunately, Barrett Sonntag made a tool to calculate the filters for you! Turning black to red ends up a whacky combination like this: invert(27%) sepia(51%) saturate(2878%) hue-rotate(346deg) brightness(104%) contrast(97%);.

SVG also has object, which is kinda neat in that it had a built-in fallback back in the day — although browser support is so good these days, I honestly have never used it. But if you're using it, you would probably have to use this filter technique to swap color on hover.

See the Pen
Background SVG Object Hovers
by Chris Coyier (@chriscoyier)
on CodePen.

Use a mask instead of a background image

This way, the SVG is still in charge of essentially drawing the shape, but the color comes from the background-color (or image! or gradient!) behind it rather than the SVG itself.

See the Pen
Background SVG Hovers with Mask
by Chris Coyier (@chriscoyier)
on CodePen.

SVG background images as data URLs

This doesn't change that much from above, but it does open up one interesting possibility: Using a variable for the internal fills. Here that is with Sass keeping the URLs as variables:

See the Pen
Background SVG Hovers with Data URL variables
by Chris Coyier (@chriscoyier)
on CodePen.

You can also do this with native CSS custom properties!

The post Change Color of SVG on Hover appeared first on CSS-Tricks.

SVG Properties and CSS

Css Tricks - Mon, 05/13/2019 - 4:44am

There are many Scalable Vector Graphics (SVG), but only certain attributes can be applied as CSS to SVG. Presentation attributes are used to style SVG elements and can be used as CSS properties. Some of these attributes are SVG-only while others are already shared in CSS, such as font-size or opacity.

For example, to change the color of a <circle> element to red, use the fill property in CSS. The fill attribute is a presentation attribute, therefore it can be used as a CSS property:

circle { fill: red; }

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

So, with that, let's take a deep and thorough dive into all of the SVG elements that are available to us as well as the CSS properties for them. We'll also look at various styling approaches, including general presentational styles and animations.

SVG Elements by Category

The presentation attributes that can be used as CSS properties can be found below. For reference, supported elements will be classified by category. This does not include deprecated elements.

Element Type Elements Container elements <a>
<defs>
<g>
<marker>
<mask>
<pattern>
<svg>
<switch>
<symbol> Filter primitive elements <feBlend>
<feColorMatrix>
<feComponentTransfer>
<feComposite>
<feConvolveMatrix>
<feDiffuseLighting>
<feDisplacementMap>
<feFlood>
<feGaussianBlur>
<feImage>
<feMerge>
<feMorphology>
<feOffset>
<feSpecularLighting>
<feTile>
<feTurbulence> Gradient elements <linearGradient>
<radialGradient>
<stop> Graphics elements <circle>
<ellipse>
<image>
<line>
<path>
<polygon>
<polyline>
<rect>
<text>
<use> Shape elements <circle>
<ellipse>
<line>
<path>
<polygon>
<polyline>
<rect> Text content elements <text>
<textPath>
<tspan> Properties shared between CSS and SVG Font properties Presentation attribute Supported elements font Text content elements font-family Text content elements font-size Text content elements font-size-adjust Text content elements font-stretch Text content elements font-style Text content elements font-variant Text content elements font-weight Text content elements Text properties Presentation attribute Supported elements direction <text>
<tspan> letter-spacing Text content elements text-decoration Text content elements unicode-bidi Text content elements word-spacing Text content elements writing-mode <text> Masking properties Presentation attribute Supported elements overflow <foreignObject>
<image>
<marker>
<pattern>
<svg>
<symbol> Interactivity properties Presentation attribute Supported elements cursor Container elements
Graphics elements Color properties Presentation attribute Supported elements color Applies to elements using:
fill
stroke
stop-color
flood-color
lighting-color Visibility properties Presentation attribute Supported elements display Graphics elements
Text content elements
<a>
<foreignObject>
<g>
<svg>
<switch> visibility Graphics elements
Text content elements SVG CSS Properties Text properties Presentation attribute Supported elements alignment-baseline <textPath>
<tspan> baseline-shift <textPath>
<tspan> dominant-baseline Text content elements glyph-orientation-horizontal Text content elements glyph-orientation-vertical Text content elements kerning Text content elements text-anchor Text content elements Clip properties Presentation attribute Supported elements clip <foreignObject>
<image>
<marker>
<pattern>
<svg>
<symbol> clip-path Container elements
Graphics elements clip-rule <clipPath> Masking properties Presentation attribute Supported elements mask Container elements
Graphics elements opacity Graphics elements
<a>
<defs>
<g>
<marker>
<pattern>
<svg>
<switch>
<symbol> Filter effects Presentation attribute Supported elements enable-background Container elements filter Container elements
Graphics elements flood-color <feFlood> flood-opacity <feFlood> lighting-color <feDiffuseLighting>
<feSpecularLighting> Gradient properties Presentation attribute Supported elements stop-color <stop> stop-opacity <stop> Interactivity properties Presentation attribute Supported elements pointer-events Graphics elements Color properties Presentation attribute Supported elements color-profile <image> referring to raster image Painting properties Presentation attribute Supported elements color-interpolation Container elements
Graphics elements color-interpolation-filters Filter primitive elements color-rendering Container elements
Graphics elements fill Shape elements
Text content elements fill-rule Shape elements
Text content elements fill-opacity Shape elements
Text content elements image-rendering <image> marker <line>
<path>
<polygon>
<polyline> marker-start <line>
<path>
<polygon>
<polyline> marker-mid <line>
<path>
<polygon>
<polyline> marker-end <line>
<path>
<polygon>
<polyline> shape-rendering Shape elements stroke Shape elements
Text content elements stroke-dasharray Shape elements
Text content elements stroke-dashoffset Shape elements
Text content elements stroke-linecap Shape elements
Text content elements stroke-linejoin Shape elements
Text content elements stroke-miterlimit Shape elements
Text content elements stroke-opacity Shape elements
Text content elements stroke-width Shape elements
Text content elements text-rendering <text> SVG 2

While presentation attributes can be used as CSS properties to style SVG, what about controlling the coordinates and dimensions of SVG elements using CSS? SVG 2, which is in Candidate Recommendation at the time of this writing, makes it is possible to style and animate these properties.

The SVG 2 specification states:

Some styling properties can be specified not only in style sheets and 'style' attributes, but also in presentation attributes. These are attributes whose name matches (or is similar to) a given CSS property and whose value is parsed as a value of that property."

Not only does it mean that SVG properties can be styled using CSS as presentation attributes or in style sheets, but this also can be applied to CSS pseudo-classes such as :hover or :active.

SVG 2 also introduces more presentation attributes that can be used as styling properties. These attributes can be found in SVG 2 specification.

Element-specific properties

It is important to note that not every SVG element will support the same CSS properties. Much like how there are CSS properties that can be applied to certain SVG elements, there are specific properties that are supported by certain SVG elements.

For example, the <circle>or <ellipse> elements support the cxand cyproperties as coordinates of the center of the shape. The <ellipse> element also supports the rx and ry properties as the radius, but the <circle> element cannot use these properties.

Geometry properties

In SVG 2, properties such as rx and ry are defined as geometry properties. Geometry properties can be used as CSS properties, just like presentation attributes such as fill or stroke properties. These CSS properties and the corresponding SVG elements include:

SVG Element Geometry Property <circle> cx
cy
r <ellipse> cx
cy
rx
ry <rect> rx
ry
height
width
x
y <path> path <image> height
width
x
y <foreignObject> height
width
x
y <svg> code>height
width
x
y Positioning SVG elements

SVG 2 also makes it is possible to position SVG elements using CSS. Let’s begin with drawing a rectangle shape having the following SVG:

<svg width="170" height="170"> <rect x="10" y="10" width="150" height="150" /> </svg>

And the following CSS:

rect { fill: #6e40aa; }

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

This will produce a rectangle shape with its coordinates set to 10, 10. With SVG 2, x and y can be applied as CSS properties:

/* This will work with SVG 2 */ rect { x: 10; y: 10; ... }

The SVG code would be reduced to this:

<svg width="170" height="170"> <rect width="150" height="150" /> </svg>

You can even set the width and height for the <rect> element using CSS like so:

rect { ... width: 150px; height: 150px; ... }

That leaves us with just the following for SVG markup:

<svg width="170" height="170"> <rect /> </svg>

See the Pen
Positioning SVG elements
by Katherine Kato (@kathykato)
on CodePen.

At the time of writing, the following demos will work in Blink (e.g. Chrome and Opera) and WebKit (e.g. Safari) browsers as these browsers support SVG 2 features. Until then, let’s dive into how to override SVG properties using CSS.

SVG shape morphing

The <path> element can be overridden with CSS to create shape morphing.

The SVG paths that morph one into the other must have the same commands and same number of points or else the morphing will not work.

Let’s start with drawing a <path> element in the shape of a triangle. Using the d property will specify the shape of the <path> element:

<svg height="220" width="300"> <path d="M150 10 L40 200 L260 200Z" /> </svg>

To get the triangle to morph into a different shape, let’s override the SVG <path> element with the d property with CSS:

path { d: path("M150, 10 L40, 200 L260, 200Z"); fill: #4c6edb; }

Let’s also add a :active pseudo-class to the <path> property so when the element is clicked, the shape will morph into a square and change its fill color. Let’s also add a transition property to make the shape morphing action appear smooth. Here is the CSS:

path:active { d: path("M150, 10 L40, 200 L260, 200 L260, 200Z"); fill: #4c6edb; transition: all 0.35s ease; }

And the SVG would be:

<svg height="220" width="300"> <path /> </svg>

See the Pen
SVG shape morphing
by Katherine Kato (@kathykato)
on CodePen.

Want another demo? Here is a cool demo from Chris Coyier demonstrating SVG shape morphing on hover!

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

Animating SVG properties

SVG properties can be animated using CSS through CSS animations and transitions.

In this demo, we will draw various SVG <circle> elements and create a wave animation. Start by drawing five <circle> elements:

<svg width="350" height="250"> <circle class="shape" /> <circle class="shape" /> <circle class="shape" /> <circle class="shape" /> <circle class="shape" /> </svg>

We’ll be using CSS variables and :nth-child() CSS pseudo-class to define each .shape class. The .shape class will have a cy of 50 and a r of 20. Each of the .shape classes will have their own cx and fill CSS properties set:

:root { --color-1: #6e40aa; --color-2: #4c6edb; --color-3: #24aad8; --color-4: #1ac7c2; --color-5: #1ddea3; } .shape { cy: 50; r: 20; } .shape:nth-child(1) { cx: 60; fill: var(--color-1); } .shape:nth-child(2) { cx: 120; fill: var(--color-2); } .shape:nth-child(3) { cx: 180; fill: var(--color-3); } .shape:nth-child(4) { cx: 240; fill: var(--color-4); } .shape:nth-child(5) { cx: 300; fill: var(--color-5); }

Here is how it should look so far.

See the Pen
Animating SVG properties: Pre-animation
by Geoff Graham (@geoffgraham)
on CodePen.

Now it’s time to animate! Start by using @keyframes rule to define the moveCircle animation:

@keyframes moveCircle { 50% { cy: 150; r: 13; } }

This will get each <circle> element to change their cy coordinates from 50 to 150 and r from 20 to 13. Add the following to the CSS to the .shape class get the animation running infinitely:

.shape { ... animation: moveCircle 1250ms ease-in-out both infinite; }

Finally, add an animation-delay to each of the .shape classes to the CSS with the exception of .shape:nth-child(1) like this:

.shape:nth-child(2) { ... animation-delay: 100ms; } .shape:nth-child(3) { ... animation-delay: 200ms; } .shape:nth-child(4) { ... animation-delay: 300ms; } .shape:nth-child(5) { ... animation-delay: 400ms; }

See the Pen
Animating SVG properties
by Katherine Kato (@kathykato)
on CodePen.

Shapes in SVG <pattern> elements can also be animated using CSS. Here is a cool demo by Dudley Storey showcasing that!

See the Pen
Screen
by Dudley Storey (@dudleystorey)
on CodePen.

Wrapping up

As SVG 1.1 is the current standard, few browsers currently support SVG 2 features. It is not recommended to put these techniques into production yet. SVG 2 implementation is currently at Candidate Recommendation stage, thus support for styling SVG geometry properties with CSS should improve in the future.

The post SVG Properties and CSS appeared first on CSS-Tricks.

Deploying a Client-Side Rendered create-react-app to Microsoft Azure

Css Tricks - Fri, 05/10/2019 - 9:54am

Deploying a React app to Microsoft Azure is simple. Except that... it isn’t. The devil is in the details. If you're looking to deploy a create-react-app — or a similar style front-end JavaScript framework that requires pushState-based routing — to Microsoft Azure, I believe this article will serve you well. We’re going to try to avoid the headaches of client and server side routing reconciliation.

First, a quick story.

Back in 2016, when Donovan Brown, a Senior DevOps Program Manager at Microsoft, had given a "but it works on my machine speech" at Microsoft Connect that year, I was still in my preliminary stages as a web developer. His talk was about micro-services and containers.

[...] Gone are the days when your manager comes running into your office and she is frantic and she has found a bug. And no matter how hard I try, I can't reproduce it and it works perfectly on my machine. She says: fine Donovan, then we are going to ship your machine because that is the only place where it works. But I like my machine, so I'm not going to let her ship it...

I had a similar sort of challenge, but it had to do with routing. I was working on a website with a React front end and ASP.NET Core back end, hosted as two separate projects that were deployed to Microsoft Azure. This meant we could deploy both apps separately and enjoy the benefits that comes with separation of concern. We also know who to git blame if and when something goes wrong. But it had downsides as well, as front-end vs. back-end routing reconciliation was one of those downsides.

One day I pushed some new code to our staging servers. I received a message shortly after telling me the website was failing on page refresh. It was throwing a 404 error. At first, I didn’t think it was my responsibility to fix the error. It had to be some server configuration issue. Turns out I was both right and wrong.

I was right to know it was a server configuration issue (though at the time, I didn’t know it had to do with routing). I was wrong to deny it my responsibility. It was only after I went on a web searching rampage that I found a use case for deploying a create-react-app to Azure under the Deployment tab on the official documentation page.

Building React for production

When building a React app for production (assuming we’re are using create-react-app), it’s worth noting the folders that get generated. Running npm run build will generate a build folder where an optimized static version of the application lives. To get the application on a live server, all we need do is feed the server the content of the build folder. If we were working on localhost, there is no live server involved, so it is not always equivalent to having the application on a live server.

Generally, the build folder will have this structure:

? build ? static ? css ? css files ? js ? js files ? media ? media files ? index.html ? other files... Client-side routing with React Router

React Router uses the HTML5 pushState history API internally. What pushState does is quite interesting. For example, navigating (or using Link in react router) from the page https://css-tricks.com to the page https://css-tricks.com/archives/ will cause the URL bar to display https://css-tricks.com/archives/ but won't cause the browser to load the page /archives or even check that it exists. Couple this with the component-based model of React, it becomes a thing to change routes while displaying different pages based on those routes — without the all-seeing eye of the server trying to serve a page in its own directory. What happens, then, when we introduce servers by pushing the code to a live server? The docs tell it better:

If you use routers that use the HTML5 pushState history API under the hood (for example, React Router with browserHistory), many static file servers will fail. For example, if you used React Router with a route for /todos/42, the development server will respond to localhost:3000/todos/42 properly, but an Express serving a production build as above will not. This is because when there is a fresh page load for a /todos/42, the server looks for the file build/todos/42 and does not find it. The server needs to be configured to respond to a request to /todos/42 by serving index.html.

Different servers require different configuration. Express, for example, requires this:

app.get('*', (req, res) => { res.sendFile(path.resolve(__dirname, 'client', 'build', 'index.html')); });

...as documented in the create-react-app docs. Keep in mind though, this assumes that we’re hosting create-react-app at the server root, which is making use of a wildcard route (*) that catches all route and respond to all route request by serving the index.html file in the build folder which sits at the root of the server application. Also, this is tightly coupled with the back-end. If that’s the case, we would most likely have this kind of folder structure (assuming the back-end is in NodeJS):

? Server ? Client (this is where your react code goes) ? build (this is the build folder, after you npm run build) ? src ? node_modules ? package.json ? other front-end files and folders ? Other back-end files and folders

Since my front-end (create-react-app) and back-end (ASP.NET) were two different projects, serving static files by navigating the directory was sort of an impossibility.

In fact, since we are deploying a static app, we do not need the back-end. As Burke Holland put it: "Static" means that we aren’t deploying any server code; just the front-end files.

I keep mentioning ASP.NET here because during the course of my research, I figured configuring Azure required a configuration file in a wwwroot folder and ASP.NET's folder structure typically has a wwwroot folder. Remember the application’s back-end was in ASP.NET? But that’s just about it. The wwwroot folder seemed to be hidden somewhere on Azure. And I can’t show you without deploying a create-react-app. So let’s go do that.

Getting started with App Services on Microsoft Azure

To get started, if you do not already have a Azure account, get a free trial then head over to the Azure portal.

  1. Navigate to All services ? Web ? App Services
    Navigating on the Azure portal from All services, to Web, to App services

  2. We want to add a new app, give it a name, subscription (should be free if you’re on a free trial, or if you already have one), resource group (create one or use existing), then click on the Create button down at the bottom of the panel.
    Creating a new App service on the Azure portal.
  3. We should get a notification that the resource has been created. But it won’t immediately show up, so hit "Refresh" — I have other resources, but the AzureReactDemo2 is what I’m using here. You’ll click on the name of your newly created app, which is AzureReactDemo2 in my case.
    Displaying all App Services on the Azure portal.
  4. The blade shows you information about your app, the navigation to the left has everything you need to manage your application (overview, activity log, deployment center...).

For example, the Deployment Center is where the app deployment is managed, Slots is where things like staging, production, test are managed. Configuration is where things like environmental variables, node versions and — an important one — Kudu are managed.

The overview screen shows a general view of the application Status, URL... Click on the URL to see the live site.

Showing the various parts of an App Service on the Azure CLI.

The app is up and running!

Showing the default live page of an App Service.

What we’ve done is create a new App Service, but we have none of our code on Azure yet. As said earlier, all we need to do is to feed Azure the content of the build folder generated by building React for production, but we don’t have one yet. So let’s go local and get some React app.

Going local

We need to create a new React app, and install react-router as a dependency.

npx create-react-app azure-react-demo cd azure-react-demo

We also want to install react-router (react-router-dom, actually)

npm i react-router-dom

All things being equal, starting the app with npm start, we should get the default page.

Showing the default page generated by React.

Because this will be about testing routes, I needed to make some pages. I’ve modified my local version and uploaded it to GitHub. I’m banking on the fact that you can find your way around react and react-router. Download a demo.

My folder looks like this:

Showing the folders and files in the modified create-react-app app.

The changed files have the following code:

// App.js import React, { Component } from "react"; import "./App.css"; import Home from "./pages/Home"; import Page1 from "./pages/Page1"; import Page2 from "./pages/Page2"; import { BrowserRouter as Router, Switch, Route } from "react-router-dom"; class App extends Component { render() { return ( <Router> <Switch> <Route exact path="/" component={Home} /> <Route path="/page1" component={Page1} /> <Route path="/page2" component={Page2} /> </Switch> </Router> ); } } export default App; // Page1.js import React from "react"; import { Link } from "react-router-dom"; const Page1 = () => { return ( <div className="page page1"> <div className="flagTop" /> <div className="flagCenter"> <h1 className="country">Argentina (PAGE 1)</h1> <div className="otherLinks"> <Link to="/page2">Nigeria</Link> <Link to="/">Home</Link> </div> </div> <div className="flagBottom" /> </div> ); }; export default Page1; // Page2.js import React from "react"; import { Link } from "react-router-dom"; const Page2 = () => { return ( <div className="page page2"> <div className="flagTop" /> <div className="flagCenter"> <h1 className="country">Nigeria (PAGE 2)</h1> <div className="otherLinks"> <Link to="/page1">Argentina</Link> <Link to="/">Home</Link> </div> </div> <div className="flagBottom" /> </div> ); }; export default Page2; /* App.css */ html { box-sizing: border-box; } body { margin: 0; } .page { display: grid; grid-template-rows: repeat(3, 1fr); height: 100vh; } .page1 .flagTop, .page1 .flagBottom { background-color: blue; } .page2 .flagTop, .page2 .flagBottom { background-color: green; } .flagCenter { display: flex; align-items: center; flex-direction: column; justify-content: center; text-align: center; } .page a { border: 2px solid currentColor; font-weight: bold; margin: 0 30px; padding: 5px; text-decoration: none; text-transform: uppercase; } .flags { display: flex; width: 100%; } .flags > .page { flex: 1; }

Running the app works locally, so the routes deliver when links are clicked and even when the page is refreshed.

Deploy the app to Azure

Now, let’s get it up on Azure! There are a few steps to make this happen.

Step 1: Head to the Deployment Center

On Azure, we need to go to the Deployment Center. There are quite a few options each with its pros and cons. We’ll be using Local Git (which means your local git app straight directly to Azure) for source control, Kudu for Build Provider.

Remember to click continue or finish when you select an option, or else, the portal will just keep staring at you.

Showing Deployment Center on the Azure portal and choosing a source control as the first step in deploying a new App Service. Showing the Build Provider section in the Deployment Center on Azure portal.

After the third step, Azure generates a local git repo for you. And it gives you a remote link to point your react app to.

One thing to note at this point. When you push, Azure will ask for your GitHub credentials. It is under the deployment tab. There are two: App and User. App credential will be specific to an app. User will be general to all the apps you as a user has Read/Write access to. You can do without User Credentials and use App credentials, but I find that after a while, Azure stops asking for credentials and just tells me authentication failed automatically. I set a custom User Credentials. Either way, you should get past that.

Showing the Deployment Credentials for the App Service on Azure portal.

In the React app, after modification, we need to build for production. This is important because what we want to upload is the content of the build folder.

We need to tell Kudu what node engine we’ll be using, or else, the build will most likely fail,
due to the reported fact that react-scripts requires a node version higher than the default set on Azure. There are other ways to do that, but the simplest is to add a nodes engine in package.json. I’m using version 10.0 here. Unfortunately, we can’t just add what we like, since Azure has Node versions it supports and the rest are unsupported. Check that with the CLI with the command: az webapp list-runtimes

Add the preferred node version to the package.json file, as in:

"engines": { "node": "10.0" } Displaying a list of Azure runtimes in the Azure CLI. Step 2: Build the App

To build the React app, let’s run npm build in the Terminal.

Step 3: Initialize the Git repo

Navigate into the build folder and initialize a Git repo in there. The URL to clone the repo is in the overview page. Depending on what credentials you’re using (App or User), it will be slightly different.

Showing the overview of the App Service on Azure and the Git clone URL. git init git add . git commit -m "Initial Commit" git remote add azure <git clone url> git push azure master

Now, visit the live app by using the URL on the overview page. As you can see, the app fails on /page2 refresh. Looking at the network tab, a 404 is thrown because the page tried to be fetched from the server — with client-side routing, as we have already set up, the page shouldn’t even be server fetched at all.

Showing the failed page request and the network tab to verify. Configuring Azure to reconcile client and server side routing

In the public folder, let’s add a web.config XML file with the following content:

<?xml version="1.0"?> <configuration> <system.webServer> <rewrite> <rules> <rule name="React Routes" stopProcessing="true"> <match url=".*" /> <conditions logicalGrouping="MatchAll"> <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" /> <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" /> <add input="{REQUEST_URI}" pattern="^/(api)" negate="true" /> </conditions> <action type="Rewrite" url="/" /> </rule> </rules> </rewrite> </system.webServer> </configuration>

I’ve intentionally decided to not format the code snippet because XML is strict about that. If you miss the formatting, the file has no effect. You can download an XML formatter for your text editor. For VSCode, that would be the XML Tools plugin.

Showing an XML formatter and an XML formatted file in VSCode.

The app can be built again at this point, although we’ll lose the Git info in the build folder since the new build overrides the old build. That means it would have to be added again, then pushed.

Now the app works as shown below! Whew.

We don’t want to have to npm run build every time — that’s where continuous deployment comes in. Check out the link below for appropriate references.

Conclusion

There is a lot to Azure, as it can do a lot for you. That’s nice because there are times when you need it to do something that seems super specific — as we’ve seen here with client and server side routing reconciliation — and it already has your back.

That said, I’ll leave you with a couple of related resources you can turn to as you look to deploying a React app to Azure.

The post Deploying a Client-Side Rendered create-react-app to Microsoft Azure appeared first on CSS-Tricks.

Syndicate content
©2003 - Present Akamai Design & Development.