Wednesday, February 1

CSS Tricks

CSS Tricks

Why monday.com is the Universal Team Management Tool for Your Team

This platform is perfect for teams sized at 2-to-200 — and gives every employee the same level of transparency.Every project management tool seeks to do the same instrumental thing: keep teams connected, on task and on deadline to get major initiatives done. But the market is getting pretty crowded, and for good reason — no platform seems to have gotten the right feel for what people need to see, and how that information should be displayed so that it’s both actionable/relevant and contextualized.That’s why monday.com is worth a shot. The platform is based off a simple, but powerful idea: that as humans, we like to feel like we’re contributing to part of a greater/effort good — an idea that sometimes gets lost in the shuffle as we focus on the details of getting stuff done. So proj...
CSS Tricks

CSS Grid Areas

I think of named grid areas in CSS Grids as bring-your-own syntactic sugar. You don't absolutely need them (you could express grid placement in other ways), but it can make that placement more intuitive. And, hey, if I'm wrong about that, correct me in the comments. Say you set up a 3-column grid: .grid { display: grid; grid-gap: 1rem; grid-template-columns: 200px 1fr 1fr; } No rows defined there; those are implicit and will appear as needed. We could define them, we just aren't, because like most situations in web design, we don't care how tall the items are — the height will grow as needed to accomodate the content.Now, how do we place something in that very top-left position in the grid? We could tell the grid to place it there like this: .item { ...
CSS Tricks

Building Skeleton Components with React

One of the advantages of building a Single Page Application (SPA) is the way navigating between pages is extremely fast. Unfortunately, the data of our components is sometimes only available after we have navigated to a specific part of our application. We can level up the user’s perceived performance by breaking the component into two pieces: the container (which displays a skeleton view when it’s empty) and the content. If we delay the rendering of the content component until we have actually received the content required, then we can leverage the skeleton view of the container thus boosting the perceived load time!Let’s get started in creating our components.  What we’re making  This is a great article that outlines how you can create a skeleton component, and th...
CSS Tricks

Demystifying JavaScript Testing

Many people have messaged me, confused about where to get started with testing. Just like everything else in software, we work hard to build abstractions to make our jobs easier. But that amount of abstraction evolves over time, until the only ones who really understand it are the ones who built the abstraction in the first place. Everyone else is left with taking the terms, APIs, and tools at face value and struggling to make things work.One thing I believe about abstraction in code is that the abstraction is not magic — it’s code. Another I thing I believe about abstraction in code is that it’s easier to learn by doing. Imagine that a less seasoned engineer approaches you. They’re hungry to learn, they want to be confident in their code, and they’re ready to start testin...
CSS Tricks

Using Feature Detection, Conditionals, and Groups with Selectors

CSS is designed in a way that allows for relatively seamless addition of new features. Since the dawn of the language, specifications have required browsers to gracefully ignore any properties, values, selectors, or at-rules they do not support. Consequently, in most cases, it is possible to successfully use a newer technology without causing any issues in older browsers.Consider the relatively new caret-color property (it changes the color of the cursor in inputs). Its support is still low but that does not mean that we should not use it today. .myInput { color: blue; caret-color: red; } Notice how we put it right next to color, a property with practically universal browser support; one that will be applied everywhere. In this case, we have not explicitly discriminated betwee...
CSS Tricks

Introducing GitHub Actions

It’s a common situation: you create a site and it’s ready to go. It’s all on GitHub. But you’re not really done. You need to set up deployment. You need to set up a process that runs your tests for you and you're not manually running commands all the time. Ideally, every time you push to master, everything runs for you: the tests, the deployment... all in one place.Previously, there were only few options here that could help with that. You could piece together other services, set them up, and integrate them with GitHub. You could also write post-commit hooks, which also help.But now, enter GitHub Actions. Actions are small bits of code that can be run off of various GitHub events, the the most common of which is pushing to master. But it's not necessarily limited to th...
CSS Tricks

How to Import a Sass File into Every Vue Component in an App

If you're working on a large-scale Vue application, chances are at some point you're going to want to organize the structure of your application so that you have some globally defined variables for CSS that you can make use of in any part of your application.This can be accomplished by writing this piece of code into every component in your application: <style lang="scss"> @import "./styles/_variables.scss"; </style> But who has time for that?! We're programmers, let's do this programmatically.  Why? You might be wondering why we would want to do something like this, especially if you're just starting out in web development. Globals are bad, right? Why would we need this? What even are Sass variables? If you already know all of this, then you can skip down ...
CSS Tricks

Why Using reduce() to Sequentially Resolve Promises Works

Writing asynchronous JavaScript without using the Promise object is a lot like baking a cake with your eyes closed. It can be done, but it's gonna be messy and you'll probably end up burning yourself.I won't say it's necessary, but you get the idea. It's real nice. Sometimes, though, it needs a little help to solve some unique challenges, like when you're trying to sequentially resolve a bunch of promises in order, one after the other. A trick like this is handy, for example, when you're doing some sort of batch processing via AJAX. You want the server to process a bunch of things, but not all at once, so you space the processing out over time. Ruling out packages that help make this task easier (like Caolan McMahon's async library), the most commonly suggested solution fo...
CSS Tricks

Getting Started with Vue Plugins

In the last months, I've learned a lot about Vue. From building SEO-friendly SPAs to crafting killer blogs or playing with transitions and animations, I've experimented with the framework thoroughly.But there's been a missing piece throughout my learning: plugins.Most folks working with Vue have either comes to rely on plugins as part of their workflow or will certainly cross paths with plugins somewhere down the road. Whatever the case, they’re a great way to leverage existing code without having to constantly write from scratch.Many of you have likely used jQuery and are accustomed to using (or making!) plugins to create anything from carousels and modals to responsive videos and type. We’re basically talking about the same thing here with Vue plugins.So, you want to make...
CSS Tricks

HTML for Zip Codes

It seems like zip codes are just numbers, right? So... <input id="zip" name="zip" type="number"> The advantage there being able to take advantage of free validation from the browser, and triggering a more helpful number-based keyboard on mobile devices.But Zach pointed out that type="number" is problematic for zip codes because zip codes can have leading zeros (e.g. a Boston zip code might be 02119). Filament group also has a little lib for fixing this.This is the perfect job for inputmode: <input id="zip" name="zip" type="text" inputmode="numeric" pattern="^(?(^00000(|-0000))|(d{5}(|-d{4})))$"> But the support is pretty bad at the time of this writing.A couple of people mentioned trying to hijack type="tel" for it, but that has its own downsides, like rejecting...
CSS Tricks

Lazy Loading Images with Vue.js Directives and Intersection Observer

When I think about web performance, the first thing that comes to my mind is how images are generally the last elements that appear on a page. Today, images can be a major issue when it comes to performance, which is unfortunate since the speed a website loads has a direct impact on users successfully doing what they came to the page to do (think conversation rates).In this article I’d like to cover the same topic using data attributes, Intersection Observer and custom directives in Vue.js.What this’ll basically do is allow us to solve two things:Store the src of the image we want to load without loading it in the first place. Detect when the image becomes visible to the user and trigger the request to load the image.Same basic lazy loading concept, but another way to ...
CSS Tricks

POSTing an Indeterminate Checkbox Value

There is a such thing as an indeterminate checkbox value. It's a checkbox (<input type="checkbox">) that isn't checked. Nor is it not checked. It's indeterminate.We can even select a checkbox in that state and style it with CSS!Some curious points though:It's only possible to set via JavaScript. There is no HTML attribute or value for it. It doesn't POST (or GET or whatever else) or have a value. It's like being unchecked. So, say you had a form like this: <form action="" method="POST" id="form"> <input name="name" type="text" value="Chris" /> <input name="vegetarian" type="checkbox" class="veg"> <input type="submit" value="Submit"> </form> And, for whatever reason, you make that checkbox indeterm...
CSS Tricks

The Way We Talk About CSS

There’s a ton of very quotable stuff from Rachel Andrew’s latest post all about CSS and how we talk about it in the community: CSS has been seen as this fragile language that we stumble around, trying things out and seeing what works. In particular for layout, rather than using the system as specified, we have so often exploited things about the language in order to achieve far more complex layouts than it was ever designed for. We had to, or resign ourselves to very simple looking web pages. Rachel goes on to argue that we probably shouldn’t disparage CSS for being so weird when there are very good reasons for why and how it works — not to mention that it’s getting exponentially more predictable and powerful as time goes by: There is frequently talk about how developers whose main area...
CSS Tricks

Styling the Gutenberg Columns Block

WordPress 5.0 is quickly approaching, and the new Gutenberg editor is coming with it. There’s been a lot of discussion in the WordPress community over what exactly that means for users, designers, and developers. And while Gutenberg is sure to improve the writing experience, it can cause a bit of a headache for developers who now need to ensure their plugins and themes are updated and compatible.One of the clearest ways you can make sure your theme is compatible with WordPress 5.0 and Gutenberg is to add some basic styles for the new blocks Gutenberg introduces. Aside from the basic HTML blocks (like paragraphs, headings, lists, and images) that likely already have styles, you’ll now have some complex blocks that you probably haven’t accounted for, like pull quotes, cover images, butto...
CSS Tricks

Valid CSS Content

There is a content property in CSS that's made to use in tandem with the ::before and ::after pseudo elements. It injects content into the element.Here's an example: <div data-done="✅" class="email"> chriscoyier@gmail.com </div> .email::before { content: attr(data-done) " Email: "; /* This gets inserted before the email address */ }The property generally takes anything you drop in there. However, there are some invalid values it won't accept. I heard from someone recently who was confused by this, so I had a little play with it myself and learned a few things. This works fine: /* Valid */ ::after { content: "1"; } ...but this does not: /* Invalid, not a string */ ::after { content: 1; } I'm not entirely sure why, but I imagi...