Sunday, 28 February 2021

CSS Border Font

Every letter in this “font” by Davor Suljic is a single div and drawn only with border. That means employing some trickery like border-radius with exotic syntax like border-radius: 100% 100% 0 0 / 37.5% 37.5% 0 0; which rounds just the top of an element with a certain chillness that works here. Plus, using pseudo-elements. I love all the wacky variations with colors, shadows, and border styles, leaning into the limits of CSS.

Drawing things with CSS has long fascinated people. Icons are a popular choice (famously, Nicolas Gallagher’s Pure CSS GUI icons from 2010), since we can draw so many shapes with CSS without even needing to lean on the all-powerful clip-path.

But as Lynn Fisher has taught us, a single div is barely a limitation at all.

Direct Link to ArticlePermalink


The post CSS Border Font appeared first on CSS-Tricks.

You can support CSS-Tricks by being an MVP Supporter.



from CSS-Tricks https://ift.tt/3bGWVQk
via IFTTT

Next.js on Netlify

(This is a sponsored post.)

If you want to put Next.js on Netlify, here’s a 5 minute tutorial¹. One of the many strengths of Next.js is that it can do server-side rendering (SSR) with a Node server behind it. But Netlify does static hosting not Node hosting, right? Well Netlify has functions, and those functions can handle the SSR. But you don’t even really need to know that, you can just use the plugin.

Need a little bit more hand-holding than that? You got it, Cassidy is doing a free Webinar about all the next Thursday (March 4th, 2021) at 9am Pacific. That way you can watch live and ask questions and stuff. Netlify has a bunch of webinars they have now smartly archived on a new resources site.

  1. I’ve also mentioned this before if it sounds familiar, the fact that it supports the best of the entire rendering spectrum is very good.

Direct Link to ArticlePermalink


The post Next.js on Netlify appeared first on CSS-Tricks.

You can support CSS-Tricks by being an MVP Supporter.



from CSS-Tricks https://ift.tt/3dYoCH1
via IFTTT

Friday, 26 February 2021

Weekly Platform News: Reduced Motion, CORS, WhiteHouse.gov, popups, and 100vw

In this week’s roundup, we highlight a proposal for a new <popup> element, check the use of prefers-reduced-motion on award-winning sites, learn how to opt into cross-origin isolation, see how WhiteHouse.gov approaches accessibility, and warn the dangers of 100vh.

Let’s get into the news!

The new HTML <popup> element is in development

On January 21, Melanie Richards from the Microsoft Edge web platform team posted an explainer for a proposed HTML <popup> element (the name is not final). A few hours later, Mason Freed from Google announced an intent to prototype this element in the Blink browser engine. Work on the implementation is taking place in Chromium issue #1168738.

A popup is a temporary (transient) and “light-dismissable” UI element that is displayed on the the “top layer” of all other elements. The goal for the <popup> element is to be fully stylable and accessible by default. A <popup> can be anchored to an activating element, such as a button, but it can also be a standalone element that is displayed on page load (e.g., a teaching UI).

Two use cases showing a white action menu with four gray menu links below a blue menu button, and another example of a blog button with a large dark blue tooltip beneath it with two paragraphs of text in white.

A <popup> is automatically hidden when the user presses the Esc key or moves focus to a different element (this is called a light dismissal). Unlike the <dialog> element, only one <popup> can be shown at a time, and unlike the deprecated <menu> element, a <popup> can contain arbitrary content, including interactive elements:

We imagine <popup> as being useful for various different types of popover UI. We’ve chosen to use an action menu as a primary example, but folks use popup-esque patterns for many different types of content.

Award-winning websites should honor the “reduce motion” preference

Earlier this week, AWWWARDS announced the winners of their annual awards for the best websites of 2020. The following websites were awarded:

All these websites are highly dynamic and show full-screen motion on load and during scroll. Unfortunately, such animations can cause dizziness and nausea in people with vestibular disorders. Websites are therefore advised to reduce or turn off non-essential animations via the prefers-reduced-motion media query, which evaluates to true for people who have expressed their preference for reduced motion (e.g., the “Reduce motion” option on Apple’s platforms). None of the winning websites do this.

/* (code from animal-crossing.com) */
@media (prefers-reduced-motion: reduce) {
  .main-header__scene {
    animation: none;
  }
}

An example of a website that does this correctly is the official site of last year’s Animal Crossing game. Not only does the website honor the user’s preference via prefers-reduced-motion, but it also provides its own “Reduce motion” toggle button at the very top of the page.

Screenshot of the animal crossing game website that is bright with a solid green header above a gold ribbon that displays menu items. Below is the main banner showing a still of the animated game with a wooden welcome to Animal Crossing sign in the foreground.

(via Eric Bailey)

Websites can now opt into cross-origin isolation

Cross-origin isolation is part of a “long-term security improvement.” Websites can opt into cross-origin isolation by adding the following two HTTP response headers, which are already supported in Chrome and Firefox:

Cross-Origin-Embedder-Policy: require-corp
Cross-Origin-Opener-Policy: same-origin

A cross-origin-isolated page relinquishes its ability to load content from other origins without their explicit opt-in (via CORS headers), and in return, the page gains access to some powerful APIs, such as SharedArrayBuffer.

if (crossOriginIsolated) {
  // post SharedArrayBuffer
} else {
  // do something else
}

The White House recommits to accessibility

The new WhiteHouse.gov website of the Biden administration was built from scratch in just six weeks with accessibility as a top priority (“accessibility was top of mind”). Microsoft’s chief accessibility officer reviewed the site and gave it the thumbs up.

The website’s accessibility statement (linked from the site’s footer) declares a “commitment to accessibility” and directly references the latest version of the Web Content Accessibility Guidelines, WCAG 2.1 (2018). This is notable because federal agencies in the USA are only required to comply with WCAG 2.0 (2008).

The Web Content Accessibility Guidelines are the most widely accepted standards for internet accessibility. … By referencing WCAG 2.1 (the latest version of the guidelines), the Biden administration may be indicating a broader acceptance of the WCAG model.

The CSS 100vw value can cause a useless horizontal scrollbar

On Windows, when a web page has a vertical scrollbar, that scrollbar consumes space and reduces the width of the page’s <html> element; this is called a classic scrollbar. The same is not the case on macOS, which uses overlay scrollbars instead of classic scrollbars; a vertical overlay scrollbar does not affect the width of the <html> element.

macOS users can switch from overlay scrollbars to classic scrollbars by setting “Show scroll bars” to ”Always” in System preferences > General.

The CSS length value 100vw is equal to the width of the <html> element. However, if a classic vertical scrollbar is added to the page, the <html> element becomes narrower (as explained above), but 100vw stays the same. In other words, 100vw is wider than the page when a classic vertical scrollbar is present.

This can be a problem for web developers on macOS who use 100vw but are unaware of its peculiarity. For example, a website might set width: 100vw on its article header to make it full-width, but this will cause a useless horizontal scrollbar on Windows that some of the site’s visitors may find annoying.

Screenshot of an article on a white background with a large black post title, post date and red tag links above a paragraph of black text. A scrollbar is displayed on the right with two large red arrows illustrating the page width, which is larger than the 100 viewport width unit.

Web developers on macOS can switch to classic scrollbars to make sure that overflow bugs caused by 100vw don’t slip under their radar. In the meantime, I have asked the CSS Working Group for comment.


The post Weekly Platform News: Reduced Motion, CORS, WhiteHouse.gov, popups, and 100vw appeared first on CSS-Tricks.

You can support CSS-Tricks by being an MVP Supporter.



from CSS-Tricks https://ift.tt/3dMvsPX
via IFTTT

The Things I Add to Tailwind CSS Right Out of the Box

In every project where I use Tailwind CSS, I end up adding something to it. Some of these things I add in every single project. I’ll share these with you, but I’m also curious what y’all are adding to your tailwind.css files.

I’ll start with myself. In each project:

  • I define -webkit-tap-highlight-color.
  • I add a bottom padding set to env(safe-area-inset-bottom).
  • I dress up unordered lists with interpuncts.

Allow me to elaborate on all three.

-webkit-tap-highlight-color

Android highlights taps on links. I’m not a fan because it obscures the element, so I turn it off for a nicer experience.

@layer base {
  html {
    -webkit-tap-highlight-color: transparent;
  }
}

@layer is a Tailwind directive. It helps avoid specificity issues by telling Tailwind which “bucket” contains a set of custom styles. It’s like pretending the cascade doesn’t exist, so there’s less to worry about when it comes to ordering CSS.

Simply removing the tap highlight color might trigger an accessibility issue since that hides an interactive cue. So, if you go this route, it’s probably a good idea (and I’m still looking for research on this if you have it) to enable :active to define provide some response to those actions. Chris has a snippet for that.

env(safe-area-inset-bottom)

This utility class handles the bottom bar on newer iPhones without the “Home” button. Without it, some elements can fall under the bar, making them unreadable and tough to tap.

@layer utilities {
  .pb-safe {
    padding-bottom: env(safe-area-inset-bottom);
  }
}

Interpuncts

I love using interpuncts with unordered lists. I won’t penalize you for looking that up. We’re basically talking about the bullet points in unordered lists. Tailwind removes them by default via Normalize. I smuggle interpuncts into each and every one of my projects.

Here’s how I go about it:

@layer utilities {
  .list-interpunct > li::before {
    content: '・';
    display: inline-block;
    float: left;
    margin: 0 0 0 -0.9em;
    width: 0.9em;
  }

  @media (min-width: 992px) {
   .list-interpunct > li::before {
      margin: 0 0 0 -1.5em;
      width: 1.5em;
    }
  }
}

We also now have ::marker to do the same thing and it’s a little easier to work with. Why am I not using it? I prefer to have control of the spacing between interpuncts and the text and I just don’t get that with ::marker. But that’s just me!

Now it’s your turn

Alright, I shared what I add to all of my Tailwind projects, so now it’s your turn. What do you add to Tailwind in your projects? Is there something you can’t do without? Let me know in the comments! I’d love ideas to start incorporating into other projects.


The post The Things I Add to Tailwind CSS Right Out of the Box appeared first on CSS-Tricks.

You can support CSS-Tricks by being an MVP Supporter.



from CSS-Tricks https://ift.tt/2NLu8Sy
via IFTTT

Google Posts: Conversion Factor — Not Ranking Factor

Posted by Greg_Gifford

While Google Posts aren’t a ranking factor, they can still be an incredibly effective resource for increasing local business conversions — when used correctly. This week’s Whiteboard Friday host, Greg Gifford, shows you how to put your best post forward.

Anatomy of a Perfect Pitch Email

Click on the whiteboard image above to open a high resolution version in a new tab!

Video Transcription

Howdy, Moz fans. Welcome to another edition of Whiteboard Fridays. I'm Greg Gifford, the Vice President of Search at SearchLab, a boutique digital marketing agency specializing in local SEO and paid search. I'm here today to talk about— you guessed it — Google Posts, the feature on Google My Business that lets you post interesting and attractive things to attract potential customers.

The importance of Google My Business

Mike Blumenthal said it first. Your Google My Business listing is your new homepage. Then we all kind of stole it, and everybody says it now. But it's totally true. It's the first impression that you make with potential customers. If someone wants your phone number, they don't have to go to your site to get it anymore. Or if they need your address to get directions or if they want to check out photos of your business or they want to see hours or reviews, they can do it all right there on the search engine results page.

If you're a local business, one that serves customers face-to-face at a physical storefront location or that serves customers at their location, like a plumber or an electrician, then you're eligible to have a Google My Business listing, and that listing is a major element of your local SEO strategy. You need to stand out from competitors and show potential customers why they should check you out. Google Posts are one of the best ways to do just that thing.

How to use Google Posts effectively

For those of you who don't know about Google Posts, they were released back in 2016, and they used to show up, up at the top of your Google My Business panel, and most businesses went crazy over them. In October of 2018, they moved them down to the very bottom of the GMB panel on desktop and out of the overview panel on mobile results, and most people kind of lost interest because they thought there would be a huge loss of visibility.

But honestly, it doesn't matter. They're still incredibly effective when they're used correctly.

Posts are basically free advertising on Google. You heard that right. They're free advertising. They show up in Google search results. Seriously, especially effective on mobile when they're mixed in with other organic results.

But even on desktop, they help your business attract potential customers and stand out from other local competitors. More importantly, they can drive pre-site conversions. You've heard about zero-click search. Now people can convert without getting to your site. They appear as a thumbnail, an image with a little bit of text underneath. Then when the user clicks on the thumbnail, the whole post pops up in a pop-up window that basically fills the window on either mobile or desktop.

Now they have no influence on ranking. They're a conversion factor, not a ranking factor. Think of it this way though. If it takes you 10 minutes to create a post and you do only one a week, that's just 40 minutes a month. If you get a conversion, isn't it worth doing? If you do them correctly, you can get a lot more than just one conversion. 

In the past, I would have told you that posts stay live in your profile for seven days, unless you use one of the post templates that includes a date range, in which case they stay live for the entire date range. But it looks like Google has changed the way that posts work, and now Google displays your 10 most recent posts in a carousel with a little arrow to scroll through. Then when you get to the end of those 10 posts, it has a link to view all of your older posts. 

Now you shouldn't pay attention to most of what you see online about Posts because there's a ridiculous amount of misinformation or simply outdated information out there.

Avoid words on the "no-no" list

Quick tip: Be careful about the text that you use. Anything with sexual connotation will get your post denied. This is really frustrating for some industries. If you put up a post about weather stripping, you get vetoed because of the word "stripping." Or if you're a plumber and you post about "toilet repairs" or "unclogging a toilet", you get denied for using the word "toilet."

So be careful if you have anything that might be on that no-no, naughty list. 

Use an enticing thumbnail



The full post contains an image. A full post has the image and then text with up to 1,500 characters, and that's all most people pay attention to. But the post thumbnail is the key to success. No one is going to see the full post if the thumbnail isn't enticing enough to click on.

Think of it like you're creating a paid search campaign. You need really compelling copy if you want more clicks on your ad or a really awesome image to attract attention if it's a banner image. The same principle applies to posts. 

Make them promotional

It's also important to be sure that your posts are promotional. People are seeing these posts in the search results before they go to your site. So in most cases they have no idea who you are yet.

The typical social fluff that you share on other social platforms doesn't work. Don't share links to blog posts or a simple "Hey, we sell this" message because those don't work. Remember, your users are shopping around and trying to figure out where they want to buy, so you want to grab their attention with something promotional.

Pick the right template

Most of the stuff out there will tell you that the post thumbnail displays 100 characters of text or about 16 words broken into 4 distinct lines. But in reality, it's different depending on which post template you use and whether or not you include a call to action link, which then replaces that last line of text.

But, hey, we're all marketers. So why wouldn't we include a CTA link, right? 

There are three main post types. In the vast majority of cases, you want to use the What's New post template. That's the one that allows for the most text in the thumbnail view, so it's easier to write something compelling. Now with the What's New post, once you include that call to action, it replaces that last line so you end up with three full lines of available text space.

Both the Event and Offer post templates include a title and then a date range. Some people dig the date range because the post stays visible for that whole date range. But now that posts stay live and visible forever, there's no advantage there. Both of those post types have that separate title line, then a separate date range line, and then the call to action link is going to be on the fourth line, which leaves you only a single line of text or just a few words to write something compelling.

Sure, the Offer post has a cool little price tag emoji there next to the title and some limited coupon functionality, but that's not a reason. You should have full coupon functionality on your site. So it's better to write something compelling with a "What's New" post template and then have the user click through on the call to action link to get to your site to get more information and convert there.

There's also a new COVID update post type, but you don't want to use it. It shows up a lot higher on your Google My Business profile, actually just below your top line information, but it's text only. Only text, no image. If you've got an active COVID post, Google hides all of your other active posts. So if you want to share a COVID info post or updates about COVID, it's better to use the What's New post template instead.

Pay attention to image cropping

The image is the frustrating part of things. Cropping is super wonky and really inconsistent. In fact, you could post the same image multiple times and it will crop slightly differently each time. The fact that the crop is slightly higher than vertical center and also a different size between mobile and desktop makes it really frustrating.

The important areas of your image can get cropped out, so half of your product ends up being gone, or your text gets cropped out, or things get really hard to read. Now there's a rudimentary cropping tool built into the image upload function with posts, but it's not locked to an aspect ratio. So then you're going to end up with black bars either on the top or on the side if you don't crop it to the correct aspect ratio, which is, by the way, 1200 pixels width by 900 pixels high.

You need to have a handle on what the safe area is within the image. So to make things easier, we created this Google Posts Cropping Guide. It's a Photoshop document with built-in guides to show you what the safe area is. You can download it at bit.ly/posts-image-guide. Make sure you put that in lowercase because it's case sensitive.

But it looks like this. Anything within that white grid is safe and that's what's going to show up in that post thumbnail. But then when you see the full post, the rest of the image shows up. So you can get really creative and have things like here's the image, but then when it pops up, there's additional text at the bottom. 

Include UTM tracking

Now, for the call to action link, you need to be sure that you include UTM tracking, because Google Analytics doesn't always attribute that traffic correctly, especially on mobile.

Now if you include UTM tagging, you can ensure that the clicks are attributed to Google organic, and then you can use the campaign variable to differentiate between the posts that you published so you'll be able to see which post generated more click-throughs or more conversions and then you can adjust your strategy moving forward to use the more effective post types. 

So for those of you that aren't super familiar with UTM tagging, it's basically adding a query string like this to the end of the URL that you're tagging so it forces Google Analytics to attribute the session a certain way that you're specifying.

So here's the structure that I recommend using when you do Google posts. It's your domain on the left. Then ?UTM_Source is GMB.Post, so it's separated. Then UTM_Medium is Organic, and UTM_Campaign is some sort of post identifier. Some people like to use Google as the source.

But at a high level, when you look at your source medium report, that traffic all gets lumped together with everything from Google. So sometimes it's confusing for clients who don't really understand that they can look at secondary dimensions to break apart that traffic. So more importantly, it's easier for you to see your post traffic separately when you look at the default source medium report.

You want to leave organic as your medium so that it's lumped and grouped correctly on the default channel report with all organic traffic. Then you enter some sort of identifier, some sort of text string or date that can let you know which post you're talking about with that campaign variable. So make sure it's something unique so that you know which post you're talking about, whether it's car post, oil post, or a date range or the title of the post so you know when you're looking in Google Analytics.

It's also important to mention that Google My Business Insights will show you the number of views and clicks, but it's a bit convoluted because multiple impressions and/or multiple clicks from the same users are counted independently. That's why adding the UTM tagging is so important for tracking accurately your performance. 

Upload videos

Final note, you can also upload videos so a video shows in the thumbnail and in the post.

So when users see that thumbnail that has a little play button on it and they click it, when the post pops up, the video will play there. Now the file size limit is 30 seconds or 75 MB, which if you got commercials, that's basically the perfect size. So even though they've been around for a few years, most businesses still ignore Posts. Now you know how to rock Posts so you'll stand out from competitors and generate more click-throughs.

Hopefully you enjoyed the video. If you've got any additional tips to share, please throw them in the comments down below. Thanks for watching, and I'll see you again next time.

Video transcription by Speechpad.com


Sign up for The Moz Top 10, a semimonthly mailer updating you on the top ten hottest pieces of SEO news, tips, and rad links uncovered by the Moz team. Think of it as your exclusive digest of stuff you don't have time to hunt down but want to read!



from The Moz Blog https://ift.tt/3sutxnb
via IFTTT

Thursday, 25 February 2021

An Interactive Guide to CSS Transitions

A wonderful post by Josh that both introduces CSS transitions and covers the nuances for using them effectively. I like the advice about transitioning the position of an element, leaving the original space it occupied alone so it doesn’t result in what he calls “doom flicker.” Six hundred and fifty years ago I created CSS Jitter Man to attempt to explain that idea.

The interactive stuff is really neat and helps explain the concepts. I’m a little jealous that Josh writes in MDX — meaning he’s got Markdown and JSX at his disposal. That means these demos can be little one-off React components. Here’s a thread that Josh did showing off how valuable that can be.

Direct Link to ArticlePermalink


The post An Interactive Guide to CSS Transitions appeared first on CSS-Tricks.

You can support CSS-Tricks by being an MVP Supporter.



from CSS-Tricks https://ift.tt/3a27zkY
via IFTTT

Ensuring the correct vertical position of large text

Tobi Reif notes how the position of custom fonts set at very large font sizes can be super different, even in the same browser across operating systems. The solution? Well, you know how there are certain CSS properties that only work within @font-face blocks? They are called “descriptors” and font-display is a popular example. There are more that are less-supported, like ascent-override, descent-override, and line-gap-override. Chrome supports them, and lo-and-behold, they can be used to fix this issue.

I really like the idea that these can be used to override the “metrics” of local (fallback) fonts to match a custom font you will load, so that, when it does, there’s little-to-no-movement. I detest FOUT (I know it’s theoretically good for performance), but I can swallow it if the text swap doesn’t move crap around so much.

Direct Link to ArticlePermalink


The post Ensuring the correct vertical position of large text appeared first on CSS-Tricks.

You can support CSS-Tricks by being an MVP Supporter.



from CSS-Tricks https://ift.tt/3qF2K6A
via IFTTT

How We Improved the Accessibility of Our Single Page App Menu

I recently started working on a Progressive Web App (PWA) for a client with my team. We’re using React with client-side routing via React Router, and one of the first elements that we made was the main menu. Menus are a key component of any site or app. That’s really how folks get around, so making it accessible was a super high priority for the team.

But in the process, we learned that making an accessible main menu in a PWA isn’t as obvious as it might sound. I thought I’d share some of those lessons with you and how we overcame them.

As far as requirements go, we wanted a menu that users could not only navigate using a mouse, but using a keyboard as well, the acceptance criteria being that a user should be able to tab through the top-level menu items, and the sub-menu items that would otherwise only be visible if a user with a mouse hovered over a top-level menu item. And, of course, we wanted a focus ring to follow the elements that have focus.

The first thing we had to do was update the existing CSS that was set up to reveal a sub-menu when a top-level menu item is hovered. We were previously using the visibility property, changing between visible and hidden on the parent container’s hovered state. This works fine for mouse users, but for keyboard users, focus doesn’t automatically move to an element that is set to visibility: hidden (the same applies for elements that are given display: none). So we removed the visibility property, and instead used a very large negative position value:

.menu-item {
  position: relative;
}

.sub-menu {
  position: absolute
  left: -100000px; /* Kicking off  the page instead of hiding visiblity */
}

.menu-item:hover .sub-menu {
  left: 0;
}

This works perfectly fine for mouse users. But for keyboard users, the sub menu still wasn’t visible even though focus was within that sub menu! In order to make the sub-menu visible when an element within it has focus, we needed to make use of :focus and :focus-within on the parent container:

.menu-item {
  position: relative;
}

.sub-menu {
  position: absolute
  left: -100000px;
}

.menu-item:hover .sub-menu,
.menu-item:focus .sub-menu,
.menu-item:focus-within .sub-menu {
  left: 0;
}

This updated code allows the the sub-menus to appear as each of the links within that menu gets focus. As soon as focus moves to the next sub menu, the first one hides, and the second becomes visible. Perfect! We considered this task complete, so a pull request was created and it was merged into the main branch.

But then we used the menu ourselves the next day in staging to create another page and ran into a problem. Upon selecting a menu item—regardless of whether it’s a click or a tab—the menu itself wouldn’t hide. Mouse users would have to click off to the side in some white space to clear the focus, and keyboard users were completely stuck! They couldn’t hit the esc key to clear focus, nor any other key combination. Instead, keyboard users would have to press the tab key enough times to move the focus through the menu and onto another element that didn’t cause a large drop down to obscure their view.

The reason the menu would stay visible is because the selected menu item retained focus. Client-side routing in a Single Page Application (SPA) means that only a part of the page will update; there isn’t a full page reload.

There was another issue we noticed: it was difficult for a keyboard user to use our “Jump to Content” link. Web users typically expect that pressing the tab key once will highlight a “Jump to Content” link, but our menu implementation broke that. We had to come up with a pattern to effectively replicate the “focus clearing” that browsers would otherwise give us for free on a full page reload.

The first option we tried was the easiest: Add an onClick prop to React Router’s Link component, calling document.activeElement.blur() when a link in the menu is selected:

const Menu = () => {
  const clearFocus = () => {
    document.activeElement.blur();
  }

  return (
    <ul className="menu">
      <li className="menu-item">
        <Link to="/" onClick={clearFocus}>Home</Link>
      </li>
      <li className="menu-item">
        <Link to="/products" onClick={clearFocus}>Products</Link>
        <ul className="sub-menu">
          <li>
            <Link to="/products/tops" onClick={clearFocus}>Tops</Link>
          </li>
          <li>
            <Link to="/products/bottoms" onClick={clearFocus}>Bottoms</Link>
          </li>
          <li>
            <Link to="/products/accessories" onClick={clearFocus}>Accessories</Link>
          </li>
        </ul>
      </li>
    </ul>
  );
}

This approach worked well for “closing” the menu after an item is clicked. However, if a keyboard user pressed the tab key after selecting one of the menu links, then the next link would become focused. As mentioned earlier, pressing the tab key after a navigation event would ideally focus on the “Jump to Content” link first.

At this point, we knew we were going to have to programmatically force focus to another element, preferably one that’s high up in the DOM. That way, when a user starts tabbing after a navigation event, they’ll arrive at or near the top of the page, similiar to a full page reload, making it much easier to access the jump link.

We initially tried to force focus on the <body> element itself, but this didn’t work as the body isn’t something the user can interact with. There wasn’t a way for it to receive focus.

The next idea was to force focus on the logo in the header, as this itself is just a link back to the home page and can receive focus. However, in this particular case, the logo was below the “Jump To Content” link in the DOM, which means that a user would have to shift + tab to get to it. No good.

We finally decided that we had to render an interact-able element, for example, an anchor element, in the DOM, at a point that’s above than the “Jump to Content” link. This new anchor element would be styled so that it’s invisible and that users are unable to focus on it using “normal” web interactions (i.e. it’s taken out of the normal tab flow). When a user selects a menu item, focus would be programmatically forced to this new anchor element, which means that pressing tab again would focus directly on the “Jump to Content” link. It also meant that the sub-menu would immediately hide itself once a menu item is selected.

const App = () => {
  const focusResetRef = React.useRef();

  const handleResetFocus = () => {
    focusResetRef.current.focus();
  };

  return (
    <Fragment>
      <a
        ref={focusResetRef}
        href="javascript:void(0)"
        tabIndex="-1"
        style=
        aria-hidden
      >Focus Reset</a>
      <a href="#main" className="jump-to-content-a11y-styles">Jump To Content</a>
      <Menu onSelectMenuItem={handleResetFocus} />
      ...
    </Fragment>
  )
}

Some notes of this new “Focus Reset” anchor element:

  • href is set to javascript:void(0) so that if a user manages to interact with the element, nothing actually happens. For example, if a user presses the return key immediately after selecting a menu item, that will trigger the interaction. In that instance, we don’t want the page to do anything, or the URL to change.
  • tabIndex is set to -1 so that a user can’t “normally” move focus to this element. It also means that the first time a user presses the tab key upon loading a page, this element won’t be focused, but the “Jump To Content” link instead.
  • style simply moves the element out of the viewport. Setting to position: fixed ensures it’s taken out of the document flow, so there isn’t any vertical space allocated to the element
  • aria-hidden tells screen readers that this element isn’t important, so don’t announce it to users

But we figured we could improve this even further! Let’s imagine we have a mega menu, and the menu doesn’t hide automatically when a mouse user clicks a link. That’s going to cause frustration. A user will have to precisely move their mouse to a section of the page that doesn’t contain the menu in order to clear the :hover state, and therefore allow the menu to close.

What we need is to “force clear” the hover state. We can do that with the help of React and a clearHover class:

// Menu.jsx
const Menu = (props) => {
  const { onSelectMenuItem } = props;
  const [clearHover, setClearHover] = React.useState(false);

  const closeMenu= () => {
    onSelectMenuItem();
    setClearHover(true);
  }

  React.useEffect(() => {
    let timeout;
    if (clearHover) {
      timeout = setTimeout(() => {
        setClearHover(false);
      }, 0); // Adjust this timeout to suit the applications' needs
    }
    return () => clearTimeout(timeout);
  }, [clearHover]);

  return (
    <ul className={`menu ${clearHover ? "clearHover" : ""}`}>
      <li className="menu-item">
        <Link to="/" onClick={closeMenu}>Home</Link>
      </li>
      <li className="menu-item">
        <Link to="/products" onClick={closeMenu}>Products</Link>
        <ul className="sub-menu">
          {/* Sub Menu Items */}
        </ul>
      </li>
    </ul>
  );
}

This updated code hides the menu immediately when a menu item is clicked. It also hides immediately when a keyboard user selects a menu item. Pressing the tab key after selecting a navigation link moves the focus to the “Jump to Content” link.

At this point, our team had updated the menu component to a point where we were super happy. Both keyboard and mouse users get a consistent experience, and that experience follows what a browser does by default for a full page reload.

Our actual implementation is slightly different than the example here so we could use the pattern on other projects. We put it into a React Context, with the Provider set to wrap the Header component, and the Focus Reset element being automatically added just before the Provider’s children. That way, the element is placed before the “Jump to Content” link in the DOM hierarchy. It also allows us to access the focus reset function with a simple hook, instead of having to prop drill it.

We have created a Code Sandbox that allows you to play with the three different solutions we covered here. You’ll definitely see the pain points of the earlier implementation, and then see how much better the end result feels!

We would love to hear feedback on this implementation! We think it’s going to work well, but it hasn’t been released to in the wild yet, so we don’t have definitive data or user feedback. We’re certainly not a11y experts, just doing our best with what we do know, and are very open and willing to learn more on the topic.


The post How We Improved the Accessibility of Our Single Page App Menu appeared first on CSS-Tricks.

You can support CSS-Tricks by being an MVP Supporter.



from CSS-Tricks https://ift.tt/3uvsXaD
via IFTTT

Boost app engagement with chat, voice, and video APIs

Sendbird is a service for helping you add social features to your app. Wanna add in-app chat? Sendbird does that. Wanna add in-app voice or video calls? Sendbird does that.

Here’s how I always think about stuff like this. Whatever the thing you are building is, you should specialize in the core of it, and not get bogged down in building essentially another product as you’re doing it. Say you want to build an app for dentists to do bookings and customer management. Please do, by the way, my dentist could really use it. You’ve got a lot of work ahead of you, the core of which is building a thing that is perfect for actual dentists and getting the UX right. In-app chat might be an important part of that, but you aren’t specifically building chat software, you’re building dentist software. Lean on Sendbird for the chat (and everything else).

To elaborate on the dentist software example for a bit, I can tell you more about my dentist. They are so eager to text me, email me, call me, even use social media, to remind me about everything constantly. But for me to communicate with them, I have to call. It’s the only way to talk to them about anything—and it’s obnoxious. If there was a dentist in town where I knew I could fire up a quick digital chat with them to book things, I’d literally switch dentists. Even better if I could click a button in a browser to call them or do a video consult. That’s just good business.

You know what else? Your new app for dentists (seriously, you should do this) is going to have to be compliant on a million standards for any dentist to buy it. This means any software you buy will need to be too. Good thing Sendbird is all set with HIPPA/HITECH, SOC 2, GDPR, and more, not to mention being hugely security-focused.

Sendbird aren’t spring chickens either, they are already trusted by Reddit, Virgin UAE, Yahoo, Meetup, and tons more.

Chat is tricky stuff, too. It’s not just a simple as shuffling a message off to another user and displaying it. Modern chat offers things like reactions, replies, and notifications. Chat needs to be friendly to poor networks and offline situations. Harder still, moderating chat activity and social control like blocking and reporting. Not only does Sendbird help with all that, their UIKit will help you build the interface as well.

Build it with Sendbird, and it’ll scale forever.

Sendbird’s client base gave us confidence that they would be able to handle our traffic and projected growth. ”

Ben Celibicic, CTO

Modern apps have modern users that expect these sort of features.


The post Boost app engagement with chat, voice, and video APIs appeared first on CSS-Tricks.

You can support CSS-Tricks by being an MVP Supporter.



from CSS-Tricks https://ift.tt/2ZRuolG
via IFTTT

The Potential Impact of Gen Z on SEO

Posted by stewartfussell

Generation Z's behaviors differ from the cohorts that came before it, creating a new challenge for businesses marketing to consumers within it. Gen Z's presence is also growing in the marketing industry itself and, as such, learning how to work with and appeal to these young people is a critical step to take sooner rather than later. 

Who is Generation Z?

Social media stars might be the first people who come to mind when you think of Gen Z (also affectionately called Zoomers), but this age group is more than just TikTokers and YouTubers. Although the purported birth years of this generation vary across different sources, Pew Research refers to them as individuals born from 1997 and onward. With that in mind, it may come as a surprise that these Americans now make up about 28.7% of the total population. For context, Baby Boomers now account for a smaller proportion of just 21.8%, and Millennials around 22%.

Even more shocking than these statistics may be the fact that the oldest members of Generation Z are now well into their twenties. While it’s easy to think of this group as teenagers and children, they’ve grown up quickly, and are now major players in the world’s economy. In fact, this group has an annual spending power of around $143 billion, and currently accounts for approximately 40% of global consumers.

It’s well known that members of this cohort are digital natives and have been raised alongside technology. In 2014, the UK’s Office of Communications tested the technological proficiency of children versus adults only to find that the average 6-year-old outperformed those in their 40s. It’s safe to assume most members of this new generation have a solid grasp of technology, and a skill set that rivals people much older. This may be even more prevalent now with the rising use of digital resources due to the COVID-19 crisis.

Pew Social Trends noted in a recent essay that much like Millennials, who faced the Great Recession during their coming-of-age years, Gen Z will be affected by the pandemic for a long time to come. With a job market that is more competitive than ever and digital skills in high demand, a career in search may become increasingly attractive. Although search engine optimization is ever-changing, its importance has been unwavering for nearly two decades, making it a stable option in an unpredictable world.

How do Zoomers interact with marketing as a whole?

When it comes to targeting this cohort, its members are creating new challenges for businesses. First and foremost, their relationships with brands are very different than those of the generations that came before them. Reports from IBM in association with the National Retail Federation found that, for Gen Z, brand loyalty must be earned. Zoomers are looking for a reflection of their personal values in brands and are prepared to hold them accountable. Beyond their resistance to conventional brand loyalty, research has also found that they are more difficult to engage.

Generally speaking, in this day and age, consumers are bombarded with thousands of ads a day and have become harder to reach. As such, it’s not shocking that a common statistic claims that members of Gen Z have the smallest attention spans of just eight seconds. However, Fast Company presents this information in a new light by explaining that they actually have “8-second filters”. These filters allow them to quickly process the tremendous amounts of information they encounter each day to hone in on what they actually care about, uniquely preparing them to glaze over advertising attempts (as they’ve been conditioned to do basically since birth).

To combat this trend, marketers have been pursuing a variety of novel strategies and methods. For example, experiential marketing has proven to be effective with Gen Z, and they're also especially excited by virtual reality.

While there are many new marketing opportunities available, social media continues to be a major channel for Gen Z engagement. This is especially true when it comes to video content on sites like YouTube and TikTok. All in all, as these consumers move away from traditional television viewership, the need for alternative marketing avenues grows.

How does Gen Z use search?

With all of this background information in mind, it’s easy to see that search is well-positioned to access this target demographic. Generation Z may not be as responsive to direct advertisements, but they’re accustomed to searching.

As a matter of fact, search engines have been around longer than Gen Z has, with the first search engine appearing in 1990, so it’s no surprise that their use is second nature to this age group. Zoomers fully understand how to use search tools, and they have the capacity to quickly evaluate SERPs prior to deciding on which link will get their click.

They’ve always had the answers to any question readily available, so they also use search for more intentional discovery. Despite their noted “8-second filter”, Fast Company additionally found that they could become deeply focused on topics they find to be worthwhile. Furthermore, their nonchalance towards brand loyalty means they may be less likely to opt for a big brand website over others.

Finally, their use and reliance on mobile devices can't be overlooked or overstated. The stereotype that people are now glued to their phones has some merit, and companies like Google have taken notice. They’ve already begun catering towards this shift, with things like mobile-first indexing and AMP pages now taking on greater importance. IBM and NRF discovered that, in a global survey of 15,600 Gen Z-ers, 60% would not use an app or site that loads too slowly. This puts the importance of mobile site speed into a greater perspective for SEOs hoping to capture this demographic through search.

The findings of a recent Fractl survey clearly align with each of these trends. They found that out of all the generations, Gen Z has the highest preference for long-tail queries. They know that a short-tail query will produce broad results, and they may not find what they’re looking for. In addition, their mobile usage has created an uptick in voice assistant search functions, which utilize these multi-word phrases as well.

Zoomers working as SEOs

Although this age group is well equipped to use search engines, it’s likely that the concept of SEO still remains somewhat foreign to them. A quick Coursera search shows that there are almost no SEO-specific college courses currently available to students. While some general digital marketing classes may have a chapter or section on SEO, that information can oftentimes be outdated due to the ever-changing nature of search. There are also a few certificate programs and online workshops, but the aforementioned issue is still present. In summary, the most accessible way for students to learn is through their own research, an internship, or some other similar experience that they happen upon.

That said, this industry can provide a fantastic career path for members of Gen Z, should they discover and choose to pursue it. Working in search allows you to develop a variety of skills from critical thinking to problem-solving and data analysis. Those in the SEO community are always up to date on the latest tech and trends, which is valuable in many facets of business. Furthermore, working within an agency provides the opportunity to learn about a vast range of industries and niches. Many SEOs even pick up web development, data science, and programming experience along the way, and these are three competencies that are in very high demand. All things considered, the many hard and soft skills that can be developed through SEO work are the foundations for being successful throughout a career.

Zoomers already have an aptitude for work in technology-based spaces, and those with the determination can pick up expertise quickly in this field. Prime examples of this include the use of SEO tools and content management systems. For instance, once a CMS such as WordPress is learned, that knowledge can be easily transferred to others like Drupal, HubSpot, and so on. The same can be said for tools like Google Analytics and Search Console, because understanding how to evaluate data within those platforms can be translated to a variety of others. In essence, SEO and Gen Z could truly be a match made in digital marketing heaven.

Understanding client-side Gen Z-ers

While SEO may not yet be a mainstream career path for most young people, those in the digital marketing field will likely encounter it at some point. As such, it’s important to keep in mind that members of this generation will also be working on the client side of search.

As previously mentioned, some Zoomers are already part of the workforce, and the presence of this cohort will only continue to grow. In the year 2020 alone, Gen Z made up approximately 24% of the worldwide workforce.

With an influx of new workers on the horizon, working with them may be a unique experience given their strong grasp of technology. On top of that, they're also more familiar with concepts like analytics and data science as those careers are seeing a boom in the higher education sector. Members of this age group shouldn't be underestimated when it comes to absorbing the ins-and-outs of SEO from the client’s point of view.

As Gen Z continues entering the workforce, likely in entry-level positions, it’s important to remember that they'll be decision-makers in a few short years. They'll have an increasing ability to influence budgeting decisions, so it's absolutely critical to think about ways to connect with them now and communicate the value of SEO to save time, energy, and money in the long run. A few steps to work through are as follows:

  • Understand that they’re eager to learn and can do so quickly.
    • Walk them through the reasoning behind each recommendation to build their knowledge over time. As with clients of any age, this improves trust and helps them to see how SEO really works.
  • Take them seriously and listen to their insights.
    • They may have concerns, as any client might when it comes to SEO strategies and how they play into the overall marketing plan. Listen to what they have to say, as they may be new, but they could still provide impactful insights.
  • Embrace novel ideas and creative thinking.
    • Fresh ideas are never a bad thing, but it can be easy to feel resistant towards those that seem to come out of left field. Fight the impulse to immediately shut these down and instead seriously consider how they could be incorporated into the project.
  • Don’t shy away from using new tools and technologies.
    • As mentioned above, Gen Z isn't intimidated by new forms of technology. Share interesting findings from tools like HotJar, Tableau, or Google Tag Manager to make SEO more exciting for them.
  • Be candid and transparent about performance analytics.
    • Be up front about the state of the site’s performance to build their confidence and appreciation for search. In the age of instant gratification, there are few things more satisfying than a positive trend line. On the other side of that, be sure to research and determine the causes for any downturns.

Conclusion

While Gen Z may be a mystery in many ways, two things are certain: they are well on their way to dominating many industries, and they shouldn't be overlooked. Likewise, if you’re not preparing for their arrival, you might already be falling behind.

Give these findings and tips some thought, and if there are already Gen Z-ers in your organization, try to take time to pick their brains. Go ahead and learn to embrace the change – as we so often do in SEO – because these TikTokers and YouTubers will only be growing in influence.


Sign up for The Moz Top 10, a semimonthly mailer updating you on the top ten hottest pieces of SEO news, tips, and rad links uncovered by the Moz team. Think of it as your exclusive digest of stuff you don't have time to hunt down but want to read!



from The Moz Blog https://ift.tt/3uDUrLp
via IFTTT

Wednesday, 24 February 2021

Teaching Web Dev for Free is Good Business

It feels like a trend (and a smart one) for tech platforms to invest in really high-quality learning material for their platform. Let’s have a gander.

Webflow University

Surely Webflow is thinking: if people invest in learning Webflow, they’ll be able to build what they need for themselves and their clients in Weblow, and they’ll stick around and be a good customer.

Jamstack Explorers

Surely Netlify is thinking: if people really grok Jamstack, they’ll build their existing and future sites using it. They’ll get comfortable using Netlify’s features to solve their problems, and they’ll stick around and be a good customer.

Salesforce Trailhead

Surely Salesforce is thinking: if we train people to learn Salesforce and build Salesforce-specific software, not only will they be a good customer, but they’ll bring more customers to us and help big companies stay good customers.

Figma Crash Course

This is not created by Figma themselves, but by Pablo Stanley, who must be thinking: I can teach people to use Figma, and along the way show them how cool and powerful Blush is, which will gain Blush good customers.

Apollo Odyssey

Surely Apollo is thinking: if y’all know GraphQL, and learned it in the context of Apollo, you probably continue using Apollo and bring it to the teams you’re on, which might make for great customers.

WP Courses 

This one is an outlier because these are paid courses, but my guess is that Automattic is thinking: there is already a ton of WordPress learning material out there, why not leverage our brand and deep expertise to make content people are willing to pay for.

Git Tutorials & Training

Surely Atlassian is thinking: if we are the place where people literally learned Git, we can sprinkle in our tooling into those lessons, and you’ll use those tools for your Git workflow, which will follow you through your entire developer career. Not to mention this is good SEO juice.

GitHub does the same thing.


Helping your customers learn your platform is certainly not a new concept. The word “webinar” exists after all. It’s a funny word, but effective. For example, AWS Marketplace sponsors CodePen emails sometimes with the idea of getting people to attend webinars about certain technologies. Wanna learn about Apache Kafka? You can do that for free coming up Thursday, February 25th. Surely AWS is thinking if people learn how this technology works, they’ll use AWS and AWS Marketplace partners to spin it up when they get to using it.

Cypress publishes their webinars. Appcues publishes their webinars. It’s not rare.

What feels a new here is the idea of packaging up learning material on a microsite with a fancy design and making it feel in-line with modern learning platforms. Like you are going to some expensive code school, except you’re getting it for free.

I’m a fan of all this. It’s good marketing for companies. It’s a good learning opportunity for everyone else. It’s also very biased. Learning materials you get directly from companies is going to tell you all about how great the technology of that company is. You should know that going in, if it’s isn’t obvious.

I’m also a fan—perhaps an even bigger fan—of paying for high-quality learning material. Our learning partner, Frontend Masters, has no particular bias to technology because you’re their customer. If they help you, they succeed and you succeed as well.


The post Teaching Web Dev for Free is Good Business appeared first on CSS-Tricks.

You can support CSS-Tricks by being an MVP Supporter.



from CSS-Tricks https://ift.tt/3bC5WtR
via IFTTT

A DRY Approach to Color Themes in CSS

The other day, Florens Verschelde asked about defining dark mode styles for both a class and a media query, without repeat CSS custom properties declarations. I had run into this issue in the past but hadn’t come up with a proper solution.

What we want is to avoid redefining—and thus repeating—custom properties when switching between light and dark modes. That’s the goal of DRY (Don’t Repeat Yourself) programming, but the typical pattern for switching themes is usually something like this:

:root {
  --background: #fff;
  --text-color: #0f1031;
  /* etc. */
}

@media (prefers-color-scheme: dark) {
  :root {
    --background: #0f1031;
    --text-color: #fff;
    /* etc. */
  }
}

See what I mean? Sure, it might not seem like a big deal in an abbreviated example like this, but imagine juggling dozens of custom properties at a time—that’s a lot of duplication!

Then I remembered Lea Verou’s trick using --var: ;, and while it didn’t hit me at first, I found a way to make it work: not with var(--light-value, var(--dark-value)) or some nested combination like that, but by using both side by side!

Certainly, someone smarter must have discovered this before me, but I haven‘t heard of leveraging (or rather abusing) CSS custom properties to achieve this. Without further ado, here’s the idea:

--color: var(--light, orchid) var(--dark, rebeccapurple);

If the --light value is set to initial, the fallback will be used (orchid), which means --dark should be set to a whitespace character (which is a valid value), making the final computed value look like this:

--color: orchid  ; /* Note the additional whitespace */

Conversely, if --light is set to a whitespace and --dark to initial, we end up with a computed value of:

--color:   rebeccapurple; /* Again, note the whitespace */

Now, this is great but we do need to define the --light and --dark custom properties, based on the context. The user can have a system preference in place (either light or dark), or can have toggled the website‘s theme with some UI element. Just like Florens‘s example, we’ll define these three cases, with some minor readability enhancement that Lea proposed using “on” and “off” constants to make it easier to understand at a glance:

:root { 
  /* Thanks Lea Verou! */
  --ON: initial;
  --OFF: ;
}

/* Light theme is on by default */
.theme-default,
.theme-light {
  --light: var(--ON);
  --dark: var(--OFF);
}

/* Dark theme is off by default */
.theme-dark {
  --light: var(--OFF);
  --dark: var(--ON);
}

/* If user prefers dark, then that's what they'll get */
@media (prefers-color-scheme: dark) {
  .theme-default {
    --light: var(--OFF);
    --dark: var(--ON);
  }
}

We can then set up all of our theme variables in a single declaration, without repetition. In this example, the theme-* classes are set to the html element, so we can use :root as a selector, as many people like to do, but you could set them on the body, if the cascading nature of the custom properties makes more sense that way:

:root {
  --text: var(--light, black) var(--dark, white);
  --bg: var(--light, orchid) var(--dark, rebeccapurple);
}

And to use them, we use var() with built-in fallbacks, because we like being careful:

body {
  color: var(--text, navy);
  background-color: var(--bg, lightgray);
}

Hopefully you’re already starting to see the benefit here. Instead of defining and switching armloads of custom properties, we’re dealing with two and setting all the others just once on :root. That’s a huge improvement from where we started.

Even DRYer with pre-processors

If you were to show me this following line of code out of context, I’d certainly be confused because a color is a single value, not two!

--text: var(--light, black) var(--dark, white);

That’s why I prefer to abstract things a bit. We can set up a function with our favorite pre-processor, which is Sass in my case. If we keep our code above defining our --light and --dark values in various contexts, we need to make a change only on the actual custom property declaration. Let’s create a light-dark function that returns the CSS syntax for us:

@function light-dark($light, $dark) {
  @return var(--light, #{ $light }) var(--dark, #{ $dark });
}

And we’d use it like this:

:root {
   --text: #{ light-dark(black, white) };
   --bg: #{ light-dark(orchid, rebeccapurple) };
   --accent: #{ light-dark(#6d386b, #b399cc) };
}

You’ll notice there are interpolation delimiters #{ … } around the function call. Without these, Sass would output the code as is (like a vanilla CSS function). You can play around with various implementations of this but the syntax complexity is up to your tastes.

How’s that for a much DRYer codebase?

More than one theme? No problem!

You could potentially do this with more than two modes. The more themes you add, the more complex it becomes to manage, but the point is that it is possible! We add another theme set of ON or OFF variables, and set an extra variable in the list of values.

.theme-pride {
  --light: var(--OFF);
  --dark: var(--OFF);
  --pride: var(--ON);
}

:root {
  --text:
    var(--light, black)
    var(--dark, white)
    var(--pride, #ff8c00)
  ; /* Line breaks are absolutely valid */

  /* Other variables to declare… */
}

Is this hacky? Yes, it absolutely is. Is this a great use case for potential, not-yet-existing CSS booleans? Well, that’s the dream.

How about you? Is this something you’ve figured out with a different approach? Share it in the comments!


The post A DRY Approach to Color Themes in CSS appeared first on CSS-Tricks.

You can support CSS-Tricks by being an MVP Supporter.



from CSS-Tricks https://ift.tt/3pLZXb7
via IFTTT

Passkeys: What the Heck and Why?

These things called  passkeys  sure are making the rounds these days. They were a main attraction at  W3C TPAC 2022 , gained support in  Saf...