Tag: State

The State Of Web Workers In 2021

You gotta appreciate the tenacity of Surma. He’s been advocating for Web Workers as a path forward to better-feeling websites for a lot of years now. He’s at it again making sure we all understand the landscape:

[…] regardless of where you look, multithreading is used everywhere. iOS empowers developers to easily parallelize code using Grand Central Dispatch, Android does this via their new, unified task scheduler WorkManager and game engines like Unity have job systems. The reason for any of these platforms to not only support multithreading, but making it as easy as possible is always the same: Ensure your app feels great.

Surma, “The State Of Web Workers In 2021”

So pretty much every platform has its own version of multi-threading, including the web. It’s just that on the web we have to sort of “fight” against the single-threaded nature of JavaScript by using Web Workers (which are “universally supported” if you’re wondering about that). The question is: use them how and for what? For the latter, Surma shows off an example of a game where “the entire app state and game logic is running in a worker.” For the former, the helper library comlink looks like a big reduction in toil.

Personally, I wish popular tooling would just kinda… do it. I don’t know what that really looks like, but it kinda feels like developer outreach isn’t really moving the needle on this. What if popular tooling like Apollo — which is in charge of a lot of “app state” — were to magically handle all of that off the main thread. Does that make sense? Is it possible?

Direct Link to ArticlePermalink


The post The State Of Web Workers In 2021 appeared first on CSS-Tricks. You can support CSS-Tricks by being an MVP Supporter.

CSS-Tricks

, ,

Custom State Pseudo-Classes in Chrome

There is an increasing number of “custom” features on the web platform. We have custom properties (--my-property), custom elements (<my-element>), and custom events (new CustomEvent('myEvent')). At one point, we might even get custom media queries (@media (--my-media)).

But that’s not all! You might have missed it because it wasn’t mentioned in Google’s “New in Chrome 90” article (to be fair, declarative shadow DOM stole the show in this release), but Chrome just added support for yet another “custom” feature: custom state pseudo-classes (:--my-state).

Built-in states

Before talking about custom states, let’s take a quick look at the built-in states that are defined for built-in HTML elements. The CSS Selectors module and the “Pseudo-classes” section of the HTML Standard specify a number of pseudo-classes that can be used to match elements in different states. The following pseudo-classes are all widely supported in today’s browsers:

User action
:hover the mouse cursor hovers over the element
:active the element is being activated by the user
:focus the element has the focus
:focus-within the element has or contains the focus
Location
:visited the link has been visited by the user
:target the element is targeted by the page URL’s fragment
Input
:disabled the form element is disabled
:placeholder-shown the input element is showing placeholder text
:checked the checkbox or radio button is selected
:invalid the form element’s value is invalid
:out-of-range the input element’s value is outside the specificed range
:-webkit-autofill the input element has been autofilled by the browser
Other
:defined the custom element has been registered

Note: For brevity, some pseudo-classes have been omitted, and some descriptions don’t mention every possible use-case.

Custom states

Like built-in elements, custom elements can have different states. A web page that uses a custom element may want to style these states. The custom element could expose its states via CSS classes (class attribute) on its host element, but that’s considered an anti-pattern.

Chrome now supports an API for adding internal states to custom elements. These custom states are exposed to the outer page via custom state pseudo-classes. For example, a page that uses a <live-score> element can declare styles for that element’s custom --loading state.

live-score {   /* default styles for this element */ }  live-score:--loading {   /* styles for when new content is loading */ }

Let’s add a --checked state to a <labeled-checkbox> element

The Custom State Pseudo Class specification contains a complete code example, which I will use to explain the API. The JavaScript portion of this feature is located in the custom element‘s class definition. In the constructor, an “element internals” object is created for the custom element. Then, custom states can be set and unset on the internal states object.

Note that the ElementInternals API ensures that the custom states are read-only to the outside. In other words, the outer page cannot modify the custom element’s internal states.

class LabeledCheckbox extends HTMLElement {   constructor() {     super();      // 1. instantiate the element’s “internals”     this._internals = this.attachInternals();      // (other code)   }    // 2. toggle a custom state   set checked(flag) {     if (flag) {       this._internals.states.add("--checked");     } else {       this._internals.states.delete("--checked");     }   }    // (other code) }

The web page can now style the custom element’s internal states via custom pseudo-classes of the same name. In our example, the --checked state is exposed via the :--checked pseudo-class.

labeled-checkbox {   /* styles for the default state */ }  labeled-checkbox:--checked {   /* styles for the --checked state */ }
Try the demo in Chrome

This feature is not (yet) a standard

Browser vendors have been debating for the past three years how to expose the internal states of custom elements via custom pseudo-classes. Google’s Custom State Pseudo Class specification remains an “unofficial draft” hosted by WICG. The feature underwent a design review at the W3C TAG and has been handed over to the CSS Working Group. In Chrome’s ”intent to ship” discussion, Mounir Lamouri wrote this:

It looks like this feature has good support. It sounds that it may be hard for web developers to benefit from it as long as it’s not widely shipped, but hopefully Firefox and Safari will follow and implement it too. Someone has to implement it first, and given that there are no foreseeable backward incompatible changes, it sounds safe to go first.

We now have to wait for the implementations in Firefox and Safari. The browser bugs have been filed (Mozilla #1588763 and WebKit #215911) but have not received much attention yet.


The post Custom State Pseudo-Classes in Chrome appeared first on CSS-Tricks.

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

CSS-Tricks

, , ,
[Top]

Takes on State

React is actually a bit of an outlier with state management. While it has first-class tools like useState and Context, you’re more own your own for reactive global state. Here’s David Ceddia with “React State Management Libraries and How to Choose” which does a good job of talking about the options. I say “outlier” because every other major JavaScript framework has its own blessed global state implementations.

To me, the concept of state is vital to front-end development. It’s like components in that way. It’s just shaking out that it’s a smart way to work on digital products. State is our own abstraction of what is happening on a site. It can be whether a sidebar is open or closed, a list of comments data, the details of logged-in users, or anything else that we need to draw and make functional UI.

That’s why it still feels surprising to me that native web components didn’t attempt to tackle the idea of state at all. I’m not informed enough to know why that is, but as an observer, I can see that developers are clamoring to find the best ways to make state work in and across web components. Most recently, I came across @vue/lit by Evan You. That is a microframework for web components that solves templating and re-rendering by using lit-html, and then incorporating reactive state with Vue’s reactivity. Looks pretty cool to me.

Evan’s idea takes the the combined weight of libraries in use to ~6kb. So how low can we go here? Krasimir Tsonev wrote “Using JavaScript module system for state management” where they use no libraries at all (arguably creating a small one of their own along the way). A state manager can just be a module we import and use that is essentially an Object with values, mutation functions, and listeners. That takes the overhead of state mangement down to just about nothing, at the cost of giving up the efficient re-rendering, better templating, and lifecycle stuff you’d get by using more robust libraries.

Speaking of not using any libraries at all, here’s Leo Bauza with “How does Viget JavaScript?” where they go into the vanilla pattern they use to add functionality on top of an HTML foundation. It looks like all functionality is applied via data-* attributes, and each data attribute has its own JavaScript module (Class) that handles that specific bit of functionality. It doesn’t look like the deal with global state here, but they do handle state rather manually within the modules.

I find all this stuff fascinating. In my own work, I bet I’m rather typical. If it’s a small baby thing, I might be up for a roll-my-own pattern. If it’s a medium-sized thing but sorta low-impact, I’d probably reach for the new-and-fancy — and maybe even experimental — takes. But the second I’m doing something big and high-impact, I find way more comfort in picking from the biggest players, even if that sometimes means heavier libraries. 😬


The post Takes on State appeared first on CSS-Tricks.

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

CSS-Tricks

,
[Top]

State of JavaScript 2020

We rounded up a bunch of published 2020 annual reports right before the year ended and compiled them into a big ol’ list. The end of the list called out a couple of in-progress surveys, one of which was the 2020 State of JavaScript. Well, the results are in and available to check out!

Just shy of 24,000 folks participated in this year’s survey… almost exactly 2,000 more than 2019.

I love charts like this:

Notice how quickly some technologies take off then start to gain negative opinions, even as the rate of adoption increases.

What I like about this particular survey (and the State of CSS) is how the data is readily available to export in addition to all the great and telling charts. That opens up the possibility of creating your own reports and gleaning your own insights. But here’s what I’ve found interesting in the short time I’ve spent looking at it:

  • React’s facing negative opinions. It’s not so much that everybody’s fleeing from it, but the “shiny” factor may be waning (coming in at 88% satisfaction versus a 93% peak in 2017). Is that because it suffers from the same frustration that devs expressed with a lack of documentation in other surveys? I don’t know, but the fact that we see both growth and a sway toward negative opinions is interesting enough that I’ll want to see where it goes in 2021.
  • Awwwww, Gulp, what happened?! Wow, what a change in perception. Its usage has dipped a bit, but the impression of it is now solidly in “negative opinions” territory. I still use it personally on a number of projects and it does exactly what I need, but I get that there are better build processes these days that don’t require writing a bunch of pipes and whatnot.
  • Hello, Svelte. It’s the most fourth most used framework (15%) but enjoys the highest level of satisfaction (89%). I’m already interested in giving it a go, but this makes me want to dive into it even more — which is consistent with the fact that it also garners the most interest of all frameworks (68%).
  • Javascript is sorta overused and sorta overly complex. Well, according to the polls. It’s just so interesting that the distribution between the opinions is almost perfectly even. At the same time, the vast majority of folks (80.6%) believe JavaScript is heading in the right direction.

Direct Link to ArticlePermalink


The post State of JavaScript 2020 appeared first on CSS-Tricks.

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

CSS-Tricks

, ,
[Top]

Custom Properties as State

Here’s a fun idea from James Stanley: a CSS file (that presumably updates daily) containing CSS custom properties for “seasonal” colors (e.g. spring is greens, fall is oranges). You’d then use the values to theme your site, knowing that those colors change slightly from day to day.

This is what I got while writing this:

:root {   --seasonal-bg: hsl(-68.70967741935485,9.419354838709678%,96%);   --seasonal-bgdark: hsl(-68.70967741935485,9.419354838709678%,90%);   --seasonal-fg: hsl(-68.70967741935485,9.419354838709678%,30%);   --seasonal-hl: hsl(-83.70967741935485,30.000000000000004%,50%);   --seasonal-hldark: hsl(-83.70967741935485,30.000000000000004%,35%); }

I think it would be more fun if the CSS file provided was just the custom properties and not the opinionated other styles (like what sets the body background and such). That way you could implement the colors any way you choose without any side effects.

This makes me think that a CDN-hosted CSS file like this could have other useful stuff, like today’s date for usage in pseudo content, or other special time-sensitive stuff. Maybe the phase of the moon? Sports scores?! Soup of the day?!

/* <div class="soup">The soup of the day is: </div> */ .soup::after {   content: var(--soupOfTheDay); /* lol kinda */ }

It’s almost like a data API that is tremendously easy to use. Pseudo content is even accessible content these days — but you can’t select the text of pseudo-elements, so don’t read this as an actual endorsement of using CSS as a content API.

Will Boyd just blogged about what is possible to put in a custom property. They are tremendously flexible. Just about anything is a valid custom property value and then the usage tends to behave just how you think it will.

body {   /* totally fine */   --rgba: rgba(255, 0, 0, 0.1);   background: var(--rgba);    /* totally fine */   --rgba: 255, 0, 0, 0.1;   background: rgba(var(--rgba));    /* totally fine */   --rgb: 255 0 0;   --a: 0.1;   background: rgb(var(--rgb) / var(--a)); }  body::after {   /* totally fine */   --song: "I need quotes to be pseudo content \A and can't have line breaks without this weird hack \A but still fairly permissive (💧💧💧) ";   content: var(--song);   white-space: pre; }

Bram Van Damme latched onto that flexiblity while covering Will’s article:

That’s why you can use CSS Custom Properties to:

perform conditional calculations

pass data from within your CSS to your JavaScript

inject skin tone / hair color modifiers onto Emoji 

toggle multiple values with one custom property (--foo: ; hack)

Bram points out this “basic” state-flipping quality that a custom property can pull off:

:root {   --is-big: 0; }  .is-big {   --is-big: 1; }  .block {   padding: calc(     25px * var(--is-big) +     10px * (1 - var(--is-big))   );   border-width: calc(     3px * var(--is-big) +     1px * (1 - var(--is-big))   ); }

Add a couple of scoops of complexity and you get The Raven (media queries with custom properties).

Will calls them “CSS variables” which is super common and understandable. You’ll read (and I have written) sentences often that are like “CSS variables (a.k.a CSS Custom Properties)” or “CSS Custom Properties (a.k.a CSS Variables.” Šime Vidas recently noted there is a rather correct way to refer to these things: --this-part is the custom property and var(--this-part) is the variable, which comes right from usage in the spec.

And that reminds me of this Vue proposal. I’m not sure if it went anywhere, but the state of a component would automatically be exposed as CSS custom properties.

<template>   <div class="text">Hello</div> </template>  <script> export default {   data() {     return {       color: 'red'     }   } } </script>  <style vars="{ color }"> .text {   color: var(--color); } </style>

By virtue of having color as part of the state of this component, then --color is available as state to the CSS of this component. I think that’s a great idea.

What if every time you used useState in React, CSS custom properties were put on the :root and were updated automatically. For example, if you did this:

import React, { useState } from 'https://cdn.skypack.dev/react@^16.13.1'; import ReactDOM from 'https://cdn.skypack.dev/react-dom@^16.13.1';  const App = () => {   const [ activeColor, setActiveColor ] = useState("red");   return(     <div className="box">       <h1>Active Color: {activeColor}</h1>       <button onClick={() => {setActiveColor("red")}}>red</button>       <button onClick={() => {setActiveColor("blue")}}>blue</button>     </div>   ); }  ReactDOM.render(<App />, document.getElementById("root"))

And you knew you could do like:

.box {   border-color: 2px solid var(--activeColor); }

Because the state automatically mapped itself to a custom property. Someone should make a useStateWithCustomProperties hook or something to do that. #freeidea

Libraries like React and Vue are for building UI. I think it makes a lot of sense that the state that they manage is automatically exposed to CSS.

And speaking of state that CSS should know about, I’ve seen quite a few demos that do fun stuff by mapping over things, like the current mouse position or scroll position, over to CSS. I don’t think it’s entirely unreasonable to ask for that data to be natively exposed to CSS. We already have the concept of environment variables, like env(safe-area-inset-top), and I could see that being used to expose page state, like env(page-scroll-percentage) or env(mouseY).


The post Custom Properties as State appeared first on CSS-Tricks.

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

CSS-Tricks

, ,
[Top]

HTTP Archive’s Annual State of the Web Report

The HTTP Archive looked at more than 7 million websites and compiled their annual report detailing how the sites were built. And there’s an enormous wealth of information about how the web changed in 2020. In fact, this report is more like an enormous book and it’s entirely fabulous. The data comes from making queries to the HTTP Archive and is broken down into various sections, such as Performance, Security, and the languages themselves, including how folks wrote HTML or CSS.

Here’s what the report has to say about the CSS they scanned:

While JavaScript far surpasses CSS in its share of page weight, CSS has certainly grown in size over the years, with the median desktop page loading 62 KB of CSS code, and 1 in 10 pages loading more than 240 KB of CSS code. Mobile pages do use slightly less CSS code across all percentiles, but only by 4 to 7 KB. While this is definitely greater than previous years, it doesn’t come close to JavaScript’s whopping median of 444 KB and top 10% of 1.2 MB

Gasp! And here’s a shocking bit of info that shortly follows:

[…] only about 7% of pages concentrate all their CSS code in one remote stylesheet, as we are often taught to do. In fact, the median page contains 3 <style> elements and 6 (!) remote stylesheets, with 10% of them carrying over 14 <style> elements and over 20 remote CSS files! While this is suboptimal on desktop, it really kills performance on mobile, where round-trip latency is more important than raw download speed.

I sort of want to quote the whole section about CSS specifically because there’s a lot of interesting facts that show how we, as a community, have a lot of work to do to improve performance and spread the good word about CSS optimization.

Direct Link to ArticlePermalink


The post HTTP Archive’s Annual State of the Web Report appeared first on CSS-Tricks.

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

CSS-Tricks

, , , ,
[Top]

A Complete State Machine Made With HTML Checkboxes and CSS

State machines are typically expressed on the web in JavaScript and often through the popular XState library. But the concept of a state machine is adaptable to just about any language, including, amazingly, HTML and CSS. In this article, we’re going to do exactly that. I recently built a website that included a “no client JavaScript” constraint and I needed one particular unique interactive feature.

The key to all this is using <form> and <input type="radio"> elements to hold a state. That state is toggled or reset with another radio <input> or reset <button> that can be anywhere on the page because it is connected to the same <form> tag. I call this combination a radio reset controller, and it is explained in more detail at the end of the article. You can add more complex state with additional form/input pairs.

It’s a little bit like the Checkbox Hack in that, ultimately, the :checked selector in CSS will be doing the UI work, but this is logically more advanced. I end up using a templating language (Nunjucks) in this article to keep it manageable and configurable.

Traffic light state machine

Any state machine explanation must include the obligatory traffic light example. Below is a working traffic light that uses a state machine in HTML and CSS. Clicking “Next” advances the state. The code in this Pen is post processed from the state machine template to fit in a Pen. We’ll get into the code in a more readable fashion later on.

Hiding/Showing table information

Traffic lights aren’t the most practical every-day UI. How about a <table> instead?

There are two states (A and B) that are changed from two different places in the design that affect changes all over the UI. This is possible because the empty <form> elements and <input> elements that hold state are at the very top of the markup and thus their state can be deduced with general sibling selectors and the rest of the UI can be reached with descendent selectors. There is a loose coupling of UI and markup here, meaning we can change the state of almost anything on the page from anywhere on the page.

General four-state component

Diagram of a generic four-state finite state machine

The goal is a general purpose component to control the desired state of the page. “Page state” here refers to the desired state of the page and “machine state” refers to the internal state of the controller itself. The diagram above shows this generic state machine with four states(A, B, C and D). The full controller state machine for this is shown below. It is built using three of the radio reset controller bits. Adding three of these together forms a state machine that has eight internal machine states (three independent radio buttons that are either on or off).

Diagram of the controller’s internal states

The “machine states” are written as a combination of the three radio buttons (i.e. M001 or M101). To transition from the initial M111 to M011, the radio button for that bit is unset by clicking on another radio <input> in the same group. To transition back, the reset <button> for the <form> attached to that bit is clicked which restores the default checked state. Although this machine has eight total states, only certain transitions are possible. For instance, there is no way to go directly from M111 to M100 because it requires two bits to be flipped. But if we fold these eight states into four states so that each page state shares two machine states (i.e. A shares states M111 and M000) then there is a single transition from any page state to any other page state.

Reusable four-state component

For reusability, the component is built with Nunjucks template macros. This allows it to be dropped into any page to add a state machine with the desired valid states and transitions. There are four required sub-components:

  • Controller
  • CSS logic
  • Transition controls
  • State classes

Controller

The controller is built with three empty form tags and three radio buttons. Each of the radio buttons checked attribute is checked by default. Each button is connected to one of the forms and they are independent of each other with their own radio group name. These inputs are hidden with display: none because they are are not directly changed or seen. The states of these three inputs comprise the machine state and this controller is placed at the top of the page.

{% macro FSM4S_controller()%}   <form id="rrc-form-Bx00"></form>   <form id="rrc-form-B0x0"></form>   <form id="rrc-form-B00x"></form>   <input data-rrc="Bx00" form="rrc-form-Bx00" style="display:none" type="radio" name="rrc-Bx00" checked="checked" />   <input data-rrc="B0x0" form="rrc-form-B0x0" style="display:none" type="radio" name="rrc-B0x0" checked="checked" />   <input data-rrc="B00x" form="rrc-form-B00x" style="display:none" type="radio" name="rrc-B00x" checked="checked" /> {% endmacro %}

CSS logic

The logic that connects the controller above to the state of the page is written in CSS. The Checkbox Hack uses a similar technique to control sibling or descendant elements with a checkbox. The difference here is that the button controlling the state is not tightly coupled to the element it is selecting. The logic below selects based on the “checked” state of each of the three controller radio buttons and any descendant element with class .M000. This state machine hides any element with the .M000 class by setting display: none !important. The !important isn’t a vital part of the logic here and could be removed; it just prioritizes the hiding from being overridden by other CSS.

{%macro FSM4S_css()%} <style>   /* Hide M000 (A1) */   input[data-rrc="Bx00"]:not(:checked)~input[data-rrc="B0x0"]:not(:checked)~input[data-rrc="B00x"]:not(:checked)~* .M000  {     display: none !important;   }    /* one section for each of 8 Machine States */  </style> {%endmacro%}

Transition control

Changing the state of the page requires a click or keystroke from the user. To change a single bit of the machine state, the user clicks on a radio button that is connected to the same form and radio group of one of the bits in the controller. To reset it, the user clicks on a reset button for the form connected to that same radio button. The radio button or the reset button is only shown depending on which state they are in. A transition macro for any valid transition is added to the HTML. There can be multiple transitions placed anywhere on the page. All transitions for states currently inactive will be hidden.

{%macro AtoB(text="B",class="", classBtn="",classLbl="",classInp="")%}   <label class=" {{class}} {{classLbl}} {{showM111_A()}} "><input class=" {{classInp}} " form="rrc-form-Bx00" type="radio" name="rrc-Bx00" />{{text}}</label>   <button class=" {{class}} {{classBtn}} {{showM000_A1()}} " type="reset" form="rrc-form-Bx00">{{text}}</button> {%endmacro%} 

State class

The three components above are sufficient. Any element that depends on state should have the classes applied to hide it during other states. This gets messy. The following macros are used to simplify that process. If a given element should be shown only in state A, the {{showA()}} macro adds the states to hide.

{%macro showA() %}   M001 M010 M100 M101 M110 M011 {%endmacro%} 

Putting it all together

The markup for the traffic light example is shown below. The template macros are imported in the first line of the file. The CSS logic is added to the head and the controller is at the top of the body. The state classes are on each of the lights of the .traffic-light element. The lit signal has a {{showA()}} macro while the “off” version of signal has the machine states for the .M000 and .M111 classes to hide it in the A state. The state transition button is at the bottom of the page.

{% import "rrc.njk" as rrc %} <!DOCTYPE html> <html lang="en"> <head>   <meta charset="UTF-8" />   <title>Traffic Light State Machine Example</title>   <link rel="stylesheet" href="styles/index.processed.css">   {{rrc.FSM4S_css()}} </head> <body>   {{rrc.FSM4S_controller()}}   <div>     <div class="traffic-light">       <div class="{{rrc.showA()}} light red-light on"></div>       <div class="M111 M000 light red-light off"></div>       <div class="{{rrc.showB()}} light yellow-light on"></div>       <div class="M100 M011 light yellow-light off"></div>       <div class="{{rrc.showC()}} light green-light on"></div>       <div class="M010 M101 light green-light off"></div>     </div>     <div>       <div class="next-state">         {{rrc.AtoC(text="NEXT", classInp="control-input",           classLbl="control-label",classBtn="control-button")}}         {{rrc.CtoB(text="NEXT", classInp="control-input",           classLbl="control-label",classBtn="control-button")}}         {{rrc.BtoA(text="NEXT", classInp="control-input",           classLbl="control-label",classBtn="control-button")}}       </div>     </div>   </div> </body> </html>

Extending to more states

The state machine component here includes up to four states which is sufficient for many use cases, especially since it’s possible to use multiple independent state machines on one page.

That said, this technique can be used to build a state machine with more than four states. The table below shows how many page states can be built by adding additional bits. Notice that an even number of bits does not collapse efficiently, which is why three and four bits are both limited to four page states.

Bits (rrcs) Machine states Page states
1 2 2
2 4 2
3 8 4
4 16 4
5 32 6

Radio reset controller details

The trick to being able to show, hide, or control an HTML element anywhere on the page without JavaScript is what I call a radio reset controller. With three tags and one line of CSS, the controlling button and controlled element can be placed anywhere after this controller. The controlled side uses a hidden radio button that is checked by default. That radio button is connected to an empty <form> element by an ID. That form has a type="reset" button and another radio input that together make up the controller.

<!-- RRC Controller --> <form id="rrc-form"></form> <label>   Show   <input form="rrc-form" type="radio" name="rrc-group" /> </label> <button type="reset" form="rrc-form">Hide</button>  <!-- Controlled by RRC --> <input form="rrc-form" class="hidden" type="radio" name="rrc-group" checked /> <div class="controlled-rrc">Controlled from anywhere</div>

This shows a minimal implementation. The hidden radio button and the div it controls need to be siblings, but that input is hidden and never needs to be directly interacted with by the user. It is set by a default checked value, cleared by the other radio button, and reset by the form reset button.

input[name='rrc-group']:checked + .controlled-rrc {   display: none; } .hidden {   display: none; }

Only two line of CSS are required to make this work. The :checked pseudo selector connects the hidden input to the sibling it is controlling. It adds the radio input and reset button that can be styled as a single toggle, which is shown in the following Pen:

Accessibility… should you do this?

This pattern works, but I am not suggesting it should be used everywhere for everything. In most cases, JavaScript is the right way to add interactivity to the web. I realize that posting this might get some heat from accessibility and semantic markup experts. I am not an accessibility expert, and implementing this pattern may create problems. Or it may not. A properly labelled button that does something to the page controlled by otherwise-hidden inputs might work out fine. Like anything else in accessibility land: testing is required.

Also, I have not seen anyone else write about how to do this and I think the knowledge is useful — even if it is only appropriate in rare or edge-case situations.


The post A Complete State Machine Made With HTML Checkboxes and CSS appeared first on CSS-Tricks.

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

CSS-Tricks

, , , , ,
[Top]

Announcing the 2020 State of CSS Survey

Last year’s State of CSS Survey yielded interesting results. There’s the quick adoption of features, like calc() and CSS custom properties. There’s also the overwhelming opinion that CSS is fun to write even as we see a growing reliance on CSS-in JS. We also saw some predictable results, like the proliferation of VS Code as a preferred code editor, the dominance of flexbox as a layout model, as well as BEM and Sass being the most adopted technologies with the highest rates of satisfaction.

Chris and Dave disussed the 2019 State of CSS results with co-creator Sacha Greif on ShopTalk Show and dive into many, many more of the results and what they tell us about our industry.

But hey, it’s been [checking my calendar] slightly over a year since that survey and it’s back with a 2020 edition. If you can take it, please do — the more years we have on record, the more interesting trends we can find. Plus, we’ve got a whole bunch of new features and technologies to evaluate, like subgrid, user preference media queries, logical properties, line-clamp(), min(), max(), yada, yada, the list goes on!

And if nothing else, check out the survey site for some bonafide CSS tricks. 😎

Direct Link to ArticlePermalink


The post Announcing the 2020 State of CSS Survey appeared first on CSS-Tricks.

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

CSS-Tricks

, , ,
[Top]

State of Jamstack 2020: Data Deep Dive

(This is a sponsored post.)

The Jamstack, a modern approach to building websites and apps, delivers better performance, higher security, lower cost of scaling, and a better developer experience. But how popular is it among developers worldwide, and what do they love and hate about it?

We at Kentico Kontent decided to take a closer look at the current state of Jamstackʼs adoption and use. Surveying more than 500 developers in four countries, we wanted to find out how long they’ve been working with the Jamstack, what they’re using this architecture for, where they typically deploy and host their projects, and more.

Based on the findings, we created The State of Jamstack 2020 Report that provides an overview of the results and comments on the most interesting facts. Now we’ve released something just as exciting:

Our free interactive data visualization page lets you dive into the data from our survey and discover how the web developers’ answers varied according to age, gender, primary programming language, and other factors.

Do you know where the majority of US developers working for large companies store their content? Or what’s their favorite static site generator? The answers may surprise you—click below to find out:

Direct Link to ArticlePermalink


The post State of Jamstack 2020: Data Deep Dive appeared first on CSS-Tricks.

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

CSS-Tricks

, , , , ,
[Top]

Practice GraphQL Queries With the State of JavaScript API

Learning how to build GraphQL APIs can be quite challenging. But you can learn how to use GraphQL APIs in 10 minutes! And it so happens I’ve got the perfect API for that: the brand new, fresh-of-the-VS-Code State of JavaScript GraphQL API.

The State of JavaScript survey is an annual survey of the JavaScript landscape. We’ve been doing it for four years now, and the most recent edition reached over 20,000 developers.

We’ve always relied on Gatsby to build our showcase site, but until this year, we were feeding our data to Gatsby in the form of static YAML files generated through some kind of arcane magic known to mere mortals as “ElasticSearch.”

But since Gatsby poops out all the data sources it eats as GraphQL anyway, we though we might as well skip the middleman and feed it GraphQL directly! Yes I know, this metaphor is getting grosser by the second and I already regret it. My point is: we built an internal GraphQL API for our data, and now we’re making it available to everybody so that you too can easily exploit out dataset!

“But wait,” you say. “I’ve spent all my life studying the blade which has left me no time to learn GraphQL!” Not to worry: that’s where this article comes in.

What is GraphQL?

At its core, GraphQL is a syntax that lets you specify what data you want to receive from an API. Note that I said API, and not database. Unlike SQL, a GraphQL query does not go to your database directly but to your GraphQL API endpoint which, in turn, can connect to a database or any other data source.

The big advantage of GraphQL over older paradigms like REST is that it lets you ask for what you want. For example:

query {   user(id: "foo123") {     name   } }

Would get you a user object with a single name field. Also need the email? Just do:

query {   user(id: "foo123") {     name     email   } }

As you can see, the user field in this example supports an id argument. And now we come to the coolest feature of GraphQL, nesting:

query {   user(id: "foo123") {     name     email     posts {        title       body     }   } }

Here, we’re saying that we want to find the user’s posts, and load their title and body. The nice thing about GraphQL is that our API layer can do the work of figuring out how to fetch that extra information in that specific format since we’re not talking to the database directly, even if it’s not stored in a nested format inside our actual database.

Sebastian Scholl does a wonderful job explaining GraphQL as if you were meeting it for the first time at a cocktail mixer.

Introducing GraphiQL

Building our first query with GraphiQL, the IDE for GraphQL

GraphiQL (note the “i” in there) is the most common GraphQL IDE out there, and it’s the tool we’ll use to explore the State of JavaScript API. You can launch it right now at graphiql.stateofjs.com and it’ll automatically connect to our endpoint (which is api.stateofjs.com/graphql). The UI consists of three main elements: the Explorer panel, the Query Builder and the Results panels. We’ll later add the Docs panels to that but let’s keep it simple for now.

The Explorer tab is part of a turbo-boosted version of GraphiQL developed and maintained by OneGraph. Much thanks to them for helping us integrate it. Be sure to check out their example repo if you want to deploy your own GraphiQL instance.

Don’t worry, I’m not going to make you write any code just yet. Instead, let’s start from an existing GraphQL query, such as the one corresponding to developer experience with React over the past four years.

Remember how I said we were using GraphQL internally to build our site? Not only are we exposing the API, we’re also exposing the queries themselves. Click the little “Export” button, copy the query in the “GraphQL” tab, paste it inside GraphiQL’s query builder window, and click the “Play” button.

Source URL
The GraphQL tab in the modal that triggers when clicking Export.

If everything went according to plan, you should see your data appear in the Results panel. Let’s take a moment to analyze the query.

query react_experienceQuery {   survey(survey: js) {     tool(id: react) {       id       entity {         homepage         name         github {           url         }       }       experience {         allYears {           year           total           completion {             count             percentage           }           awarenessInterestSatisfaction {             awareness             interest             satisfaction           }           buckets {             id             count             percentage           }         }       }     }   } }

First comes the query keyword which defines the start of our GraphQL query, along with the query’s name, react_experienceQuery. Query names are optional in GraphQL, but can be useful for debugging purposes.

We then have our first field, survey, which takes a survey argument. (We also have a State of CSS survey so we needed to specify the survey in question.) We then have a tool field which takes an id argument. And everything after that is related to the API results for that specific tool. entity gives you information on the specific tool selected (e.g. React) while experience contains the actual statistical data.

Now, rather than keep going through all those fields here, I’m going to teach you a little trick: Command + click (or Control + click) any of those fields inside GraphiQL, and it will bring up the Docs panel. Congrats, you’ve just witnessed another one of GraphQL’s nifty tricks, self-documentation! You can write documentation directly into your API definition and GraphiQL will in turn make it available to end users.

Changing variables

Let’s tweak things a bit: in the Query Builder, replace “react” with “vuejs” and you should notice another cool GraphQL thing: auto-completion. This is quite helpful to avoid making mistakes or to save time! Press “Play” again and you’ll get the same data, but for Vue this time.

Using the Explorer

We’ll now unlock one more GraphQL power tool: the Explorer. The Explorer is basically a tree of your entire API that not only lets you visualize its structure, but also build queries without writing a single line of code! So, let’s try recreating our React query using the explorer this time.

First, let’s open a new browser tab and load graphiql.stateofjs.com in it to start fresh. Click the survey node in the Explorer, and under it the tool node, click “Play.” The tool’s id field should be automatically added to the results and — by the way — this is a good time to change the default argument value (“typescript”) to “react.”

Next, let’s keep drilling down. If you add entity without any subfields, you should see a little squiggly red line underneath it letting you know you need to also specify at least one or more subfields. So, let’s add id, name and homepage at a minimum. Another useful trick: you can automatically tell GraphiQL to add all of a field’s subfields by option+control-clicking it in the Explorer.

Next up is experience. Keep adding fields and subfields until you get something that approaches the query you initially copied from the State of JavaScript site. Any item you select is instantly reflected inside the Query Builder panel. There you go, you just wrote your first GraphQL query!

Filtering data

You might have noticed a purple filters item under experience. This is actually they key reason why you’d want to use our GraphQL API as opposed to simply browsing our site: any aggregation provided by the API can be filtered by a number of factors, such as the respondent’s gender, company size, salary, or country.

Expand filters and select companySize and then eq and range_more_than_1000. You’ve just calculated React’s popularity among large companies! Select range_1 instead and you can now compare it with the same datapoint among freelancers and independent developers.

It’s important to note that GraphQL only defines very low-level primitives, such as fields and arguments, so these eq, in, nin, etc., filters are not part of GraphQL itself, but simply arguments we’ve defined ourselves when setting up the API. This can be a lot of work at first, but it does give you total control over how clients can query your API.

Conclusion

Hopefully you’ve seen that querying a GraphQL API isn’t that big a deal, especially with awesome tools like GraphiQL to help you do it. Now sure, actually integrating GraphQL data into a real-world app is another matter, but this is mostly due to the complexity of handling data transfers between client and server. The GraphQL part itself is actually quite easy!

Whether you’re hoping to get started with GraphQL or just learn enough to query our data and come up with some amazing new insights, I hope this guide will have proven useful!

And if you’re interested in taking part in our next survey (which should be the State of CSS 2020) then be sure to sign up for our mailing list so you can be notified when we launch it.

State of JavaScript API Reference

You can find more info about the API (including links to the actual endpoint and the GitHub repo) at api.stateofjs.com.

Here’s a quick glossary of the terms used inside the State of JS API.

Top-Level Fields

  • Demographics: Regroups all demographics info such as gender, company size, salary, etc.
  • Entity: Gives access to more info about a specific “entity” (library, framework, programming language, etc.).
  • Feature: Usage data for a specific JavaScript or CSS feature.
  • Features: Same, but across a range of features.
  • Matrices: Gives access to the data used to populate our cross-referential heatmaps.
  • Opinion: Opinion data for a specific question (e.g. “Do you think JavaScript is moving in the right direction?”).
  • OtherTools: Data for the “other tools” section (text editors, browsers, bundlers, etc.).
  • Resources: Data for the “resources” section (sites, blogs, podcasts, etc.).
  • Tool: Experience data for a specific tool (library, framework, etc.).
  • Tools: Same, but across a range of tools.
  • ToolsRankings: Rankings (awareness, interest, satisfaction) across a range of tools.

Common Fields

  • Completion: Which proportion of survey respondents answered any given question.
  • Buckets: The array containing the actual data.
  • Year/allYears: Whether to get the data for a specific survey year; or an array containing all years.

The post Practice GraphQL Queries With the State of JavaScript API appeared first on CSS-Tricks.

CSS-Tricks

, , , ,
[Top]