By Bogdan Sandu
Some Articles About Accessibility I’ve Saved Recently IV
- A guide to designing accessible, WCAG-compliant focus indicators — Sara Soueidan says you can make more accessible focus outlines by doing your own, rather than leaving it to the browser — as long as you do it right. Deep dive!
- a11y-syntax-highlighting — Eric Bailey’s repo of code syntax highlighting themes for a variety of software that are both attractive and meet WCAG color contrast guidelines (including support for Windows High Contrast mode as well).
- Respecting Users’ Motion Preferences — Michelle Barker with a guide on when and how to honor people’s
prefers-reduced-motion
setting. While there is no one right way, it should be done. It’s interesting how many things might apply. Properties liketransition
andanimation
are fairly obvious, but did you think ofscroll-behavior
or things specifically in JavaScript (where you can also test for a preference)? - Accessibility testing — Jeremy Keith: “When you commission an accessibility audit, you should hope to get feedback that’s mostly in that third category—interactive widgets.” Don’t waste an accessibility expert’s time telling you about color contrast problems because you can find and fix those yourself fairly easily.
- The effect of CSS on screen readers — Part of me wishes the effect of CSS on screen readers was “nothing” but Jozsef Polgar notes there are some things CSS does affect. A classic is setting
list-style: none
on lists will force them to not read as lists in VoiceOver. Jozsef points to Ben Meyer’s article covering similar ground. - In Quest of Search — Sara again, this time weighing in on
<search>
. I’ve heard mostly negative things (like, why the focus on this when there are so many bigger fish to fry, like<dialog>
andinert
), but Sara is all for it. I agree that we might as well have an element that gives us a freerole="search"
like we get with<nav>
and<main>
. - Accessible Palette: stop using HSL for color systems — Eugene Fedorenko says, “While HSL and HSV are fine choices for choosing a single color, they’re not suitable for building a color system, as they simply transform the RGB model and ignore the complexities of human perception.” It seems like everyone who has looked into next-gen color formats is a fan, but I haven’t wrapped my mind around them yet. Things like LCh, Lch(ab), HCL, LCH(uv)… There is starting to be some trickles of browser support.
- One last time: custom styling radio buttons and checkboxes — Scott O’Hara notes that you can entirely replace these inputs with custom styling, and do it accessibly. Part of doing it right is dealing with every possible state. Worth noting: without replacing everything, you can get pretty far in styling checkboxes/radios by just changing
width
/height
and theaccent-color
, as Dave and I noted here. - Understanding Logical Focus Order — Rachel Leggett explains it is “the idea that someone navigating your webpage with a keyboard (i.e. without a mouse) will encounter elements in an order that makes sense.” Nearly anytime you use the
order
property, you’re probably interferring here. But less obviously, hidden elements that remain interactive can confuse logical focus order. - Assistiv Labs — I didn’t realize there was a tool in the vein of CrossBrowserTesting or BrowserStack that allowed you to test in JAWS and NVDA and stuff — but there is! Just the other day I wanted to test in JAWS, so I spun up a (paid) copy of Parallels with my (paid) copy of Windows 10 and used my (40-minute test version) of JAWS to test. While it worked, it was not particularly cheap or without significant technical debt. This seems easier, although I haven’t actually tried it yet.
The post Some Articles About Accessibility I’ve Saved Recently IV appeared first on CSS-Tricks. You can support CSS-Tricks by being an MVP Supporter.
Create Your Own Automated Social Images With Resoc
There has been a lot of talk about automated social images lately. GitHub has created its own. A WordPress plugin has been acquired by Jetpack. There is definitely interest! People like Ryan Filler and Zach Leatherman have implemented social images on their websites. They had to code a lot of things on their own. But the landscape is changing and tools are available to smooth the process.
In this tutorial, we are going to create our own automated social images with HTML and CSS, integrate them to an Eleventy blog — mostly by configuration — and deploy our site to Netlify.
If you really, really can’t wait, check the result or browse the project!
What are social images again?
In the <head>
section of HTML, we insert a few Open Graph markups:
<meta property="og:title" content="The blue sky strategy" /> <meta property="og:description" content="Less clouds, more blue" /> <meta property="og:image" content="/sky-with-clouds.jpg" />
When we share this page on Facebook, we and our friends see this:

LinkedIn, Twitter, WhatsApp, Slack, Discord, iMessage… All these sites behave pretty much the same way: they provide a visual “card” that accompanies the link, giving it more space and context.
Twitter has its own set of markups with its Twitter Cards, but they are very similar. And Twitter falls back to Open Graph when it can’t find them.
It is natural for our pages to have a title and a description. But in the screenshot above, they are quite small compared to the space and attention the picture of sky and clouds gets — not to mention the size of the clickable area. That’s the power of the social image. It’s easy to understand the impact these images can have when a link is shared.
From Level 0 to Level 3
Not all social images are created equal. These are not official terms, but let’s consider numbered “levels” on how impactful these social image cards can be.
Level 0
The most basic social image is no image. The link might be lost in a sea of content with the small area and not much visual.

Level 1
A classic technique is to create a site-wide social image. While this solution might seem to offer a good outcome-to-effort ratio, one could argue this is worse than no image at all. Sure, we get some attention, but the reaction might be negative, especially if people see a lot of links to this website that all look the same. It risks feeling repetitive and unnecessary.

Level 2
The next level is standard in blogs and media sites: the social image of a post. Each post has its own featured image, and they differ from one post to another. This practice is totally legitimate for a news site, where the photo complements the page content. The potential drawback here is that it requires effort to find and create artwork for each and every published post.
That might lead to a bit of laziness. We’ve all been exposed to images that are obviously stock photos. It might get attention, but perhaps not the kind of attention you actually want.

Level 3
The final level: per-page, content-rich, meaningful social images. CSS-Tricks is doing just this. The team’s social images are branded. They share the same layout. They mention the post title, along with the author’s name and profile picture, something the regular title and description could not show. They grab attention and are memorable.

There is an obvious requirement with this approach: automation. It is out of question to create unique images for every possible link. Just think of the overhead. We’d need some programmatic solution to help with the heavy lifting.
Let’s start a blog with blog posts that have unique social images
To give ourselves a nice little excuse (and sandbox) to build out unique social images, we’ll put together a quick blog. When I write and publish an article to this blog, I follow a quick two-step process:
- Write and publish the article
- Post the published URL to my social network accounts
This is when social images must shine. We want to give our blog its best shot at being noticed. But that’s not our only goal. This blog should establish our personal brand. We want our friends, colleagues, and followers to remember us when they see our social posts. We want something that’s repeatable, recognizable, and representative of ourselves.
Creating a blog is a lot or work. Although automated social images are cool, it’s unwise to spend too much time on them. (Chris came to the same conclusion at the end of 2020). So, in the interest of efficiency, we’re making an Eleventy site. Eleventy is a simple static site generator. Instead of starting from scratch, let’s use one of the starter projects. In fact, let’s pick the first one, eleventy-base-blog.

Visit the eleventy-base-blog GitHub page and use it as a template:

Let’s create the repository, and set a repository name, description. We can make it public or private, it doesn’t matter.
Next, we clone our repository locally, install packages, and run the site:
git clone [your repo URL] cd my-demo-blog ### Or whatever you named it npm install npm run serve
Our site running is running at http://localhost:8080
.
Now let’s deploy it. Netlify makes this a super quick (and free!) task. (Oh, and spoiler alert: our social images automation relies on a Netlify Function.)
So, let’s go to Netlify and create an account, that is, if you don’t already have one. Either way, create a new site:

Go through the process of allowing Netlify to access the blog repository.

Netlify deploys our site:

After a minute or so, the blog is deployed:

One image template to rule them all
Our social images are going to be based on an image template. To design this template, we are going to use the technologies we already know and love: HTML and CSS. HTML doesn’t turn itself into images auto-magically, but there are tools for this, the most famous being headless Chrome with Puppeteer.
However, instead of building our social image stack ourselves, we use the Resoc Image Template Development Kit. So, from the project root we can run this in the terminal:
npx itdk init resoc-templates/default -m title-description
This command creates a new image template in the resoc-templates/default
directory. It also opens up in a new browser window.

We could use this template as-is, but that only gets us to Level 2 on “impactful” spectrum. What we need to make this go all the way up to Level 3 and match the CSS-Tricks template is:
- the page title aligned to the right with a bit of negative space on the left.
- a footer at the bottom that contains a background gradient made from two colors we are going to use throughout the blog
- the post author’s name and profile picture
If we head back to the browser, we can see in the Parameters panel of the template viewer that the template expects two parameters: a title and description. That’s just the template we chose when we ran -m title-description
in the terminal as we set things up. But we can add more parameters by editing resoc-templates/default/resoc.manifest.json
. Specifically, we can remove the second parameter to get:
{ "partials": { "content": "./content.html.mustache", "styles": "./styles.css.mustache" }, "parameters": [ { "name": "title", "type": "text", "demoValue": "A picture is worth a thousand words" } ] }
The viewer reflects the change in the browser:

It’s time to design the image itself, which we can do in resoc-templates/default/content.html.mustache
:
<div class="wrapper"> <main> <h1>{{ title }}</h1> </main> <footer> <img src="profil-pic.jpg" /> <h2>Philippe Bernard</h2> </footer> </div>
That’s just regular HTML. Well, except {{ title }}
. This is Mustache, the templating framework Resoc uses to inject parameter values into the template. We can even type some text in the “Title” field to see it working:

Looking at the previews, notice that we’re missing an image, profil-pic.jpg
. Copy your best profile picture to resoc-templates/default/profil-pic.jpg
:

It’s time to write the CSS in resoc-templates/default/styles.css.mustache
. The point of this post isn’t how to style the template, but here’s what I ended up using:
@import url('https://fonts.googleapis.com/css2?family=Anton&family=Raleway&display=swap'); .wrapper { display: flex; flex-direction: column; } main { flex: 1; display: flex; flex-direction: column; justify-content: center; position: relative; } h1 { text-align: right; margin: 2vh 3vw 10vh 20vw; background: rgb(11,35,238); background: linear-gradient(90deg, rgba(11,35,238,1) 0%, rgba(246,52,12,1) 100%); -webkit-text-fill-color: transparent; -webkit-background-clip: text; font-family: 'Anton'; font-size: 14vh; text-transform: uppercase; text-overflow: ellipsis; display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; } h2 { color: white; margin: 0; font-family: 'Raleway'; font-size: 10vh; } footer { flex: 0 0; min-height: 20vh; display: flex; align-items: center; background: rgb(11,35,238); background: linear-gradient(90deg, rgba(11,35,238,1) 0%, rgba(246,52,12,1) 100%); padding: 2vh 3vw 2vh 3vw; } footer img { width: auto; height: 100%; border-radius: 50%; margin-right: 3vw; }
Most of the sizes rely on vw
and vh
units to help anticipate the various contexts that the template might be rendered. We are going to follow Facebook’s recommndations, which are 1200×630. Twitter Cards, on the other hand, are sized differently. We could render images in a low resolution, like 600×315, but let’s go with 1200×630 so we we only need to work in pixels.
The viewer renders the Facebook preview at 1200×630 and scales it down to fit the screen. If the preview fulfills your expectations, so will the actual Open Graph images.
So far, the template matches our needs:

What about the image?
There is one little thing to add before we are done with the template. Some of our blog posts will have images, but not all of them. In situations where a post doesn’t have an image, it would be cool to use the image to fill the space on the left.
This is a new template parameter, so we need to update resoc-templates/default/resoc.manifest.json
once again:
{ "partials": { "content": "./content.html.mustache", "styles": "./styles.css.mustache" }, "parameters": [ { "name": "title", "type": "text", "demoValue": "A picture is worth a thousand words" }, { "name": "sideImage", "type": "imageUrl", "demoValue": "https://resoc.io/assets/img/demo/photos/pexels-photo-371589.jpeg" } ] }
Let’s declare an additional div
in resoc-templates/default/content.html.mustache
:
<div class="wrapper"> <main> {{#sideImage}} <div class="sideImage"></div> {{/sideImage}} <h1>{{ title }}</h1> </main> <footer> <img src="profil-pic.jpg" /> <h2>Philippe Bernard</h2> </footer> </div>
The new {{#sideImage}} ... {{/sideImage}}
syntax is a Mustache section. It’s only present when the sideImage
parameter is defined.
We need a little extra CSS to handle the image. Notice that we’re able to use the Mustache syntax here to inset the background-image
value for a specific post. Here’s how I approached it in the resoc-templates/default/styles.css.mustache
file:
{{#sideImage}} .sideImage { position: absolute; width: 100%; height: 100%; background-image: url({{{ sideImage }}}); background-repeat: no-repeat; background-size: auto 150vh; background-position: -35vw 0vh; -webkit-mask-image: linear-gradient(45deg, rgba(0,0,0,0.5), transparent 40%); } {{/sideImage}}
Our template looks great!

We commit our template:
git add resoc-templates git commit -m "Resoc image template"
Before we automate the social images, let’s generate one manually, just as a teaser. The viewer provides a command line to generate the corresponding image for our testing purposes:

Copy it, run it from a terminal and open output-image.jpg
:

Social images automation
OK, so we created one image via the command line. What should we do now? Call it as many times as there are pages on our blog? This sounds like a boring task, and there is a deeper issue with this approach: time. Even if creating a single image took something like two seconds, we can multiply by the number of pages and we easily see the effort grow and grow.
The original Eleventy blog template is generated almost instantly, but we should wait about a minute for something as marginal as social images? This is not acceptable.
Instead of performing this task at build time, we are going to defer it, lazy style, with a Netlify Function and a Netlify on-demand builder. Actually, we aren’t actually dealing directly with a Netlify Function — an Eleventy plugin is going to handle this for us.
Let’s install that now. We can add the Resoc Social Image plugin for Eleventy, along with its companion Netlify plugin, with this command:
npm install --save-dev @resoc/eleventy-plugin-social-image @resoc/netlify-plugin-social-image
Why two plugins? The first one is dedicated to Eleventy, while the second one is framework-agnostic (for example, it can be used for Next.js).
Edit .eleventy.js
at the root of the project so that we’re importing the plugin:
const pluginResoc = require("@resoc/eleventy-plugin-social-image");
Configure it near the top of .eleventy.js
, right after the existing eleventyConfig.addPlugin
:
eleventyConfig.addPlugin(pluginResoc, { templatesDir: 'resoc-templates', patchNetlifyToml: true });
templatesDir
is where we stored our image template. patchNetlifyToml
is asking the plugin to configure @resoc/netlify-plugin-social-image
in netlify.toml
for us.
We want all our pages to have automated social images. So, let’s open the master template, _includes/layouts/base.njk
, and add this near the top of the file:
{% set socialImageUrl %} {%- resoc template = "default", slug = (title or metadata.title) | slug, values = { title: title or metadata.title, sideImage: featuredImage } -%} {% endset %}
This declares a new variable named socialImageUrl
. The content of this variable is provided by the resoc
short code, which takes three parameters:
- The
template
is the sub directory of our template (it is inresoc-templates/default
). - The
slug
is used to build the social image URL (e.g./social-images/brand-new-post.jpg
). We slug-ify the page title to provide a unique and sharable URL. - The
values
are the content, as defined inresoc-templates/default/resoc.manifest.json
.title
is obvious, because pages already have a title.sideImage
is set to a meta namedfeaturedImage
, which we are going to define for illustrated pages.
Now we can open up _includes/layouts/base.njk
, place our cursor in the <head>
, add some new markup to populate all that stuff
<meta name="og:title" content="{{ title or metadata.title }}"/> <meta name="og:description" content="{{ description or metadata.description }}"/> <meta name="og:image" content="{{ socialImageUrl }}"/> <meta name="og:image:width" content="1200"/> <meta name="og:image:height" content="630"/>
The title and description markups are similar to the existing <title>
and <meta name="description">
. We’re using socialImageUrl
as-is for the og:image
meta. We also provide the social image dimensions to round things out.
Automated social images are ready!
Let’s deploy this
When we deploy the blog again, all pages will show the text-only version of our template. To see the full version , we assign an image to an existing page. that requires us to edit one of the posts — I created four posts and am editing the fourth one, posts/fourthpost.md
— so there’s a featuredImage
entry after the existing meta:
--- title: This is my fourth post. description: This is a post on My Blog about touchpoints and circling wagons. date: 2018-09-30 tags: second tag layout: layouts/post.njk featuredImage: https://resoc.io/assets/img/demo/photos/pexels-pixabay-459653.jpg ---
Using an external URL is enough here, but we normally drop images in an img
directory with Eleventy and provide the base URL once and for all in _includes/layouts/base.njk
.
Build the site again:
npm run build
When running git status
, we might notice two modified files in addition to the ones we edited ourselves. In .gitignore
, the plugin added resoc-image-data.json
. This file stores our social image data used internally by the Netlify plugin, and netlify.toml
now contains the Netlify plugin configuration.
Deploy time!
git commit -a -m "Automated social images" git push
Netlify is notified and deploys the site. Once the latest version is online, share the homepage somewhere (e.g. Slack it to yourself or use the Facebook debugger). Here’s how the social card looks for the homepage, which does not contain an image:

And here’s how it looks for a post that does contain an image:

Perfect!
Conclusion
So far, automated social images have mostly been a matter of developers willing to explore and play around with lots of different ideas and approaches, some easy and some tough. We kept things relatively simple.
With a few lines of code, we were able to quickly setup automated social images on a blog based on Eleventy and hosted on Netlify. The part we spent the most time on was the image template, but that’s not a problem. With the viewer and Mustache already integrated, we focused on what we know, love, and value: web design.
Hopefully something like the Resoc image template dev kit and its related tools will help make the automated social images go from being a niche hobby into the mainstream.
The post Create Your Own Automated Social Images With Resoc appeared first on CSS-Tricks. You can support CSS-Tricks by being an MVP Supporter.
Okhsv and Okhsl
There is an old Russian fable where Okhsv and Okhsl are on a rowboat and Okhsv says to Okhsl, “What are the known shortcomings of HSL and HSV color pickers in design applications?” I kid, I kid. But really, what are they?
Björn Ottosson shows the two classics:

Despite color picking playing a big role in a lot of applications, the design of color pickers isn’t a particularly well researched topic. While some variation exist in the widgets themselves, the choice of HSL or HSV is mostly taken for granted, with only a few exceptions.
Is their dominance well deserved or would it be possible to create better alternatives?
It’s all rather above my head, but I certainly support the idea of researching and exploring things that so many of us just take for granted. There is a whole playground comparing different possibilities. It’s not so much about the UI/UX of the picker itself, but how the range of colors is expressed in the picker area.
Direct Link to Article — Permalink
The post Okhsv and Okhsl appeared first on CSS-Tricks. You can support CSS-Tricks by being an MVP Supporter.
Vite + _____
Vite, “Next Generation Frontend Tooling” from Evan You, has been capturing a lot of attention. I’ve heard rave reviews from developers, even in private chats (you gotta try this!). Being from Evan, Vite works great with Vue, but Vue doesn’t seem to be the only first-class citizen of Vite. The plugins support Vue and React just the same and it looks like configurations for lit, Preact, and Svelte are easy.
It’s interesting to see other technologies try to get on the bandwagon, almost certainly for the wicked speed. I believe it uses esbuild, which is known for speed, for… some things?… under the hood, but not bundling. Just noting some of this bandwagon stuff happening like…
- Sam Richard making Eleventy work with Vite.
- Ben Holmes made Slinkity, which “duct-tapes” (see Smashing article) Eleventy and Vite together.
- Michael Shilman makes Storybook work with Vite.
- Fred K. Schott notes that Astro has moved to Vite.
- Anthony Fu has a “starter pack” called Vitesse that smashes together lots of opinionated tools all together with Vite.
- There are sandboxes starting to use it, like StackBlitz, and Replit is clearly stoked about it.
- Vue-specific projects are moving to it, for example a Vite-specific Nuxt and Vite-specific VuePress.
Hey, people like speed and good DX. Always worth noting when you see this much movement.
The post Vite + _____ appeared first on CSS-Tricks. You can support CSS-Tricks by being an MVP Supporter.
Building an Angular Data Grid With Filtering
(This is a sponsored post.)
Kendo UI makes it possible to go from a basic idea to a full-fledged app, thanks to a massive component library. We’re talking well over 100 components that are ready for you to drop into your app at will, whether it’s React, Angular or Vue you’re working in — they just work. That is because Kendo UI is actually a bundle of four JavaScript libraries, each built natively for their respective framework. But more than that, as we’ve covered before, the components are super themeable to the extent that you can make them whatever you want.
But here’s the real kicker with Kendo UI: it takes care of the heavy lifting. The styling is great and all, but what separates Kendo UI from other component frameworks is the functionality it provides right out of the box.
Case in point: data. Rather than spending all your time figuring out the best way to bind data to a component, that’s just a given which ultimately allows you to focus more of your time on theming and getting the UI just right.
Perhaps the best way to see how trivial Kendo UI makes working with data is to see it in action, so…
Let’s look at the Angular Grid component
This is the Kendo UI for Angular Data Grid component. Lots of data in there, right? We’re looking at a list of employees that displays a name, image, and other bits of information about each person.
Like all of Kendo UI’s components, it’s not like there’s one data grid component that they square-pegged to work in multiple frameworks. This data grid was built from scratch and designed specifically to work for Angular, just as their KendoReact Grid component is designed specifically for React.
Now, normally, a simple <table>
element might do the trick, right? But Kendo UI for Angular’s data grid is chockfull of extras that make it a much better user experience. Notice right off the bat that it provides interactive functionality around things like exporting the data to Excel or PDF. And there are a bunch of other non-trivial features that would otherwise take a vast majority of the time and effort to make the component.
Filtering
Here’s one for you: filtering a grid of data. Say you’re looking at a list of employees like the data grid example above, but for a company that employees thousands of folks. It’d be hard to find a specific person without considering a slew of features, like search, sortable columns, and pagination — all of which Kendo UI’s data grid does.
Users can quickly parse the data bound to the Angular data grid. Filtering can be done through a dedicated filter row, or through a filter menu that pops up when clicking on a filter icon in the header of a column.

Kendo UI’s documentation is great. Here’s how fast we can get this up and running.
First, import the component
No tricks here — import the data grid as you would any other component:
import { Component, OnInit, ViewChild } from '@angular/core'; import { DataBindingDirective } from '@progress/kendo-angular-grid'; import { process } from '@progress/kendo-data-query'; import { employees } from './employees'; import { images } from './images';
Next, call the component
@Component({ selector: 'my-app', template: ` <kendo-grid> // ... </kendo-grid> ` })
This is incomplete, of course, because next we have to…
Configure the component
The key feature we want to enable is filtering, but Kendo’s Angular Grid takes all kinds of feature parameters that can be enabled in one fell swoop, from sorting and grouping, to pagination and virtualization, to name a few.
Filtering? It’s a one-liner to bind it to the column headers.
@Component({ selector: 'my-app', template: ` <kendo-grid [kendoGridBinding]="gridView" kendoGridSelectBy="id" [selectedKeys]="mySelection" [pageSize]="20" [pageable]="true" [sortable]="true" [groupable]="true" [reorderable]="true" [resizable]="true" [height]="500" [columnMenu]="{ filter: true }" > // etc. </kendo-grid> ` })
Then, mark up the rest of the UI
We won’t go deep here. Kendo UI’s documentation has an excellent example of how that looks. This is a good time to work on the styling as well, which is done in a styles
parameter. Again, theming a Kendo UI component is a cinch.
So far, we have a nice-looking data grid before we even plug any actual data into it!

And, finally, bind the data
You may have noticed right away when we imported the component that we imported “employee” data in the process. We need to bind that data to the component. Now, this is where someone like me would go run off in a corner and cry, but Kendo UI makes it a little too easy for that to happen.
// Active the component on init export class AppComponent implements OnInit { // Bind the employee data to the component @ViewChild(DataBindingDirective) dataBinding: DataBindingDirective; // Set the grid's data source to the employee data file public gridData: any[] = employees; // Apply the data source to the Grid component view public gridView: any[]; public mySelection: string[] = []; public ngOnInit(): void { this.gridView = this.gridData; } // Start processing the data public onFilter(inputValue: string): void { this.gridView = process(this.gridData, { filter: { // Set the type of logic (and/or) logic: "or", // Defining filters and their operators filters: [ { field: 'full_name', operator: 'contains', value: inputValue }, { field: 'job_title', operator: 'contains', value: inputValue }, { field: 'budget', operator: 'contains', value: inputValue }, { field: 'phone', operator: 'contains', value: inputValue }, { field: 'address', operator: 'contains', value: inputValue } ], } }).data; this.dataBinding.skip = 0; } // ... }
Let’s see that demo again
That’s a heckuva lot of power with a minimal amount of effort. The Kendo UI APIs are extensive and turn even the most complex feature dead simple.
And we didn’t even get to all of the other wonderful goodies that we get with Kendo UI components. Take accessibility. Could you imagine all of the consideration that needs to go into making a component like this accessible? Like all of the other powerful features we get, Kendo UI tackles accessibility for us as well, taking on the heavy lifting that goes into making a keyboard-friendly UI that meets WCAG 2.0 Alice standards and is compliant with Section 508 and WAI-ARIA standards.
The post Building an Angular Data Grid With Filtering appeared first on CSS-Tricks. You can support CSS-Tricks by being an MVP Supporter.