Web Standards

CSS Houdini Could Change the Way We Write and Manage CSS

Css Tricks - Thu, 03/28/2019 - 4:14am

CSS Houdini may be the most exciting development in CSS. Houdini is comprised of a number of separate APIs, each shipping to browsers separately, and some that have already shipped (here's the browser support). The Paint API is one of them. I’m very excited about it and recently started to think about how I can use it in my work.

One way I’ve been able to do that is to use it as a way to avoid reinventing the wheel. We’ll go over that in this post while comparing it with methods we currently use in JavaScript and CSS. (I won’t dig into how to write CSS Houdini because there are great articles like this, this and this.)

Houdini brings modularity and configurations to CSS

The way CSS Houdini works brings two advantages: modularity and configurability. Both are common ways to make our lives as developers easier. We see these concepts often in the JavaScript world, but less-so with CSS world… until now.

Here’s a table the workflows we have for some use cases, comparing traditional CSS with using Houdini. I also added JavaScript for further comparison. You can see CSS Houdini allows us to use CSS more productively, similar to how the JavaScript world had evolved into components.

Traditional CSS CSS Houdini JavaScript When we need a commonly used snippets Write it from scratch or copy-paste from somewhere. Import a worklet for it. Import a JS library. Customize the snippet for the use case Manually tweak the value in CSS. Edit custom properties that the worklet exposes. Edit configs that the library provides. Sharing code Share code for the raw styles, with comments on how to tweak each piece. Share the worklet (in the future, to a package management service) and document custom properties. Share the library to a package management service (like npm) and document how to use and configure it. Modularity

With Houdini, you can import a worklet and start to use it with one line of code.

<script> CSS.paintWorklet.addModule('my-useful-paint-worklet.js'); </script>

This means there’s no need to implement commonly used styles every time. You can have a collection of your own worklets which can be used on any of your projects, or even shared with each other.

If you're looking for modularity for HTML and JavaScript in additional to styles, then web components is the solution.

It’s very similar to what we already have in the JavaScript world. Most people won’t re-implement commonly used functions, like throttling or deep-copying objects. We simply import libraries, like Lodash.

I can imagine we could have CSS Houdini package management services if the popularity of CSS Houdini takes off, and anyone could import worklets for interesting waterfall layouts, background patterns, complex animation, etc.

Configurability

Houdini works well with CSS variables, which largely empowers itself. With CSS variables, a Houdini worklet can be configured by the user.

.my-element { background-image: paint(triangle); --direction: top; --size: 20px; }

In the snippet, --direction and --size are CSS variables, and they’re used in the triangle worklet (defined by the author of the triangle worklet). The user can change the property to update how it displays, even dynamically updating CSS variables in JavaScript.

If we compare it to what we already have in JavaScript again, JavaScript libraries usually have options that can be passed along. For example, we can pass values for speed, direction, size and so on to a carousel library to make it perform the way we want. Offering these APIs at the element level in CSS is very useful.

A Houdini workflow makes my development process much more efficient

Let’s see a complete example of how this whole thing can work together to make development easier. We’ll use a tooltip design pattern as an example. I find myself using this pattern often in different websites, yet somehow re-implement for each new project.

Let’s briefly walk through my old experience:

  1. OK, I need a tooltip.
  2. It’s a box, with a triangle on one side. I’ll use a pseudo-element to draw the triangle.
  3. I can use the transparent border trick to draw the triangle.
  4. At this time, I most likely dig up my past projects to copy the code. Let me think… this one needs to point up, which side is transparent?
  5. Oh, the design requires a border for the tooltip. I have to use another pseudo-element and fake a border for the pointing triangle.
  6. What? They decide to change the direction of the triangle?! OK, OK. I will tweak all the values of both triangles...

It’s not rocket science. The whole process may only take five minutes. But let’s see how it can be better with Houdini.

I built a simple worklet to draw a tooltip, with many options to change its looks. You can download it on GitHub.

Here’s my new process, thanks to Houdini:

  1. OK, I need a tooltip.
  2. I’ll import this tooltip worklet and use it.
  3. Now I’ll modify it using custom properties.
<div class="tooltip-1">This is a tip</div> <script>CSS.paintWorklet.addModule('my-tooltip-worklet.js')</script> <style> .tooltip-1 { background-image: paint(tooltip); padding: calc(var(--triangle-size) * 1px + .5em) 1em 1em; --round-radius: 0; --background-color: #4d7990; --triangle-size: 20; --position: 20; --direction: top; --border-color: #333; --border-width: 2; color: #fff; } </style>

Here’s a demo! Go ahead and play around with variables!

CSS Houdini opens a door to modularized, configurable styles sharing. I look forward to seeing developers using and sharing CSS Houdini worklets. I’m trying to add more useful examples of Houdini usage. Ping me if you have ideas, or want to contribute to this repo.

The post CSS Houdini Could Change the Way We Write and Manage CSS appeared first on CSS-Tricks.

Jetpack Gutenberg Blocks

Css Tricks - Thu, 03/28/2019 - 2:47am

I remember when Gutenberg was released into core, because I was at WordCamp US that day. A number of months have gone by now, so I imagine more and more of us on WordPress sites have dipped our toes into it. I just wrote about our first foray here on CSS-Tricks and using Gutenberg to power our newsletter.

Jetpack, of course, was ahead of the game. Jetpack adds a bunch of special, powerful blocks to Gutenberg that it's easy to see how useful they can be.

Here they are, as of this writing:

Maps! Subscriptions! GIFs! There are so many good ones. Here's a look at a few more:

The form widget, I hear, is the most popular.

You get a pretty powerful form builder right within your editor:

Instant Markdown Processing

Jetpack has always enabled Markdown support for WordPress, so it's nice that there is a Markdown widget!

PayPal Selling Blocks

There is even basic eCommerce blocks, which I just love as you can imagine how empowering that could be for some folks.

You can read more about Jetpack-specific Gutenberg blocks in their releases that went out for 6.8 and 6.9. Here at CSS-Tricks, we use a bunch of Jetpack features.

The post Jetpack Gutenberg Blocks appeared first on CSS-Tricks.

A Gutenburg-Powered Newsletter

Css Tricks - Thu, 03/28/2019 - 2:42am

I like Gutenberg, the new WordPress editor. I'm not oblivious to all the conversation around accessibility, UX, and readiness, but I know how hard it is to ship software and I'm glad WordPress got it out the door. Now it can evolve for the better.

I see a lot of benefit to block-based editors. Some of my favorite editors that I use every day, Notion and Dropbox Paper, are block-based in their own ways and I find it effective. In the CMS context, even moreso. Add the fact that these aren't just souped-up text blocks, but can be anything! Every block is it's own little configurable world, outputting anything it needs to.

I'm using Gutenberg on a number of sites, including my personal site and my rambling email site, where the content is pretty basic. On a decade+ old website like CSS-Tricks though, we need to baby step it. One of our first steps was moving our newsletter authoring into a Gutenberg setup. Here's how we're doing that.

Gutenberg Ramp

Gutenberg Ramp is a plugin with the purpose of turning Gutenberg on for some areas and not for others. In our case, I wanted to turn on Gutenberg just for newsletters, which is a Custom Post Type on our site. With the plugin installed and activated, I can do this now in our functions.php:

if (function_exists('gutenberg_ramp_load_gutenberg')) { gutenberg_ramp_load_gutenberg(['post_types' => [ 'newsletters' ]]); }

Which works great:

Classic editor for posts, Gutenberg for the Newsletters Custom Post Type

We already have 100+ newsletters in there, so I was hoping to only flip on Gutenberg over a certain date or ID, but I haven't quite gotten there yet. I did open an issue.

What we were doing before: pasting in HTML email gibberish

We ultimately send out the email from MailChimp. So when we first started hand-crafting our email newsletter, we made a template in MailChimp and did our authoring right in MailChimp:

The MailChimp Editor

Nothing terrible about that, I just much prefer when we keep the clean, authored content in our own database. Even the old way, we ultimately did get it into our database, but we did it in a rather janky way. After sending out the email, we'd take the HTML output from MailChimp and copy-paste dump it into our Newsletter Custom Post Type.

That's good in a way: we have the content! But the content is so junked up we can basically never do anything with it other than display it in an <iframe> as the content is 100% bundled up in HTML email gibberish.

Now we can author cleanly in Gutenberg

I'd argue that the writing experience here is similar (MailChimp is kind of a block editor too), but nicer than doing it directly in MailChimp. It's so fast to make headers, lists, blockquotes, separators, drag and drop images... blocks that are the staple of our newsletter.

Displaying the newsletter

I like having a permanent URL for each edition of the newsletter. I like that the delivery mechanism is email primarily, but ultimately these are written words that I'd like to be a part of the site. That means if people don't like email, they can still read it. There is SEO value. I can link to them as needed. It just feels right for a site like ours that is a publication.

Now that we're authoring right on the site, I can output <?php the_content() ?> in a WordPress loop just like any other post or page and get clean output.

But... we have that "old" vs. "new" problem in that old newsletters are HTML dumps, and new newsletters are Gutenberg. Fortunately this wasn't too big of a problem, as I know exactly when the switch happened, so I can display them in different ways according to the ID. In my `single-newsletters.php`:

<?php if (get_the_ID() > 283082) { ?> <main class="single-newsletter on-light"> <article class="article-content"> <h1>CSS-Tricks Newsletter #<?php the_title(); ?></h1> <?php the_content() ?> </article> </main> <?php } else { // Classic Mailchimp HTML dump ?> <div class="newsletter-iframe-wrap"> <iframe class="newsletter-iframe" srcdoc="<?php echo htmlspecialchars(get_the_content()); ?>"></iframe> </div> <?php } ?>

At the moment, the primary way we display the newsletters is in a little faux phone UI on the newsletters page, and it handles both just fine:

Old and new newsletters display equally well, it's just the old newsletters need to be iframed and I don't have as much design control. So how do they actually get sent out?

Since we aren't creating the newsletters inside MailChimp anymore, did we have to find another way to send them out? Nope! MailChimp can send out a newsletter based on an RSS feed.

And WordPress is great at coughing up RSS feeds for Custom Post Yypes. You can do...

/feed/?post_type=your-custom-post-type

But... for us, I wanted to make sure that any of those old HTML dump emails never ended up in this RSS feed, so that the new MailChimp RSS feed would never see them an accidentally send them. So I ended up making a special Page Template that outputs a custom RSS feed. I figured that would give us ultimate control over it if we ever need it for even more things.

<?php /* Template Name: RSS Newsletterss */ the_post(); $id = get_post_meta($post->ID, 'parent_page_feed_id', true); $args = array( 'showposts' => 5, 'post_type' => 'newsletters', 'post_status' => 'publish', 'date_query' => array( array( 'after' => 'February 19th, 2019' ) ) ); $posts = query_posts($args); header('Content-Type: '.feed_content_type('rss-http').'; charset='.get_option('blog_charset'), true); echo '<?xml version="1.0" encoding="'.get_option('blog_charset').'"?'.'>'; ?> <rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" <?php do_action('rss2_ns'); ?>> <channel> <title>CSS-Tricks Newsletters RSS Feed</title> <atom:link href="<?php self_link(); ?>" rel="self" type="application/rss+xml" /> <link><?php bloginfo_rss('url') ?></link> <description><?php bloginfo_rss("description") ?></description> <lastBuildDate><?php echo mysql2date('D, d M Y H:i:s +0000', get_lastpostmodified('GMT'), false); ?></lastBuildDate> <language><?php echo get_option('rss_language'); ?></language> <sy:updatePeriod><?php echo apply_filters( 'rss_update_period', 'hourly' ); ?></sy:updatePeriod> <sy:updateFrequency><?php echo apply_filters( 'rss_update_frequency', '1' ); ?></sy:updateFrequency> <?php do_action('rss2_head'); ?> <?php while( have_posts()) : the_post(); ?> <item> <title><?php the_title_rss(); ?></title> <link><?php the_permalink_rss(); ?></link> <comments><?php comments_link(); ?></comments> <pubDate><?php echo mysql2date('D, d M Y H:i:s +0000', get_post_time('Y-m-d H:i:s', true), false); ?></pubDate> <dc:creator><?php the_author(); ?></dc:creator> <?php the_category_rss(); ?> <guid isPermaLink="false"><?php the_guid(); ?></guid> <description><![CDATA[<?php the_excerpt_rss(); ?>]]></description> <content:encoded><![CDATA[<?php the_content(); ?>]]></content:encoded> <wfw:commentRss><?php echo get_post_comments_feed_link(); ?></wfw:commentRss> <slash:comments><?php echo get_comments_number(); ?></slash:comments> <?php rss_enclosure(); ?> <?php do_action('rss2_item'); ?> </item> <?php endwhile; ?> </channel> </rss> Styling...

With a MailChimp RSS campaign, you still have control over the outside template like any other campaign:

But then content from the feed just kinda gets dumped in there. Fortunately, their preview tool does go grab content for you so you can actually see what it will look like:

And then you can style that by injecting a <style> block into the editor area yourself.

That gives us all the design control we need over the email, and it's nicely independent of how we might choose to style it on the site itself.

The post A Gutenburg-Powered Newsletter appeared first on CSS-Tricks.

Next Genpm

Css Tricks - Wed, 03/27/2019 - 12:20pm

So many web projects use npm to pull in their dependencies, for both the front end and back. npm install and away it goes, pulling thousands of files into a node_modules folder in our projects to import/require anything. It's an important cog in the great machine of web development.

While I don't believe the npm registry has ever been meaningfully challenged, the technology around it regularly faces competition. Yarn certainly took off for a while there. Yarn had lockfiles which helped us ensure our fellow developers and environments had the exact same versions of things, which was tremendously beneficial. It also did some behind-the-scenes magic that made it very fast. Since then, npm now also has lockfiles and word on the street is it's just as fast, if not faster.

I don't know enough to advise you one way or the other, but I do find it fascinating that there is another next generation of npm puller-downer-thingies that is coming to a simmer.

  • pnpm is focused on speed and efficiency when running multiple projects: "One version of a package is saved only ever once on a disk."
  • Turbo is designed for running directly in the browser.
  • Pika's aim is that, once you've downloaded all the dependencies, you shouldn't be forced to use a bundler, and should be able to use ES6 imports if you want. UNPKG is sometimes used in this way as well, in how it gives you URLs to packages directly pulled from npm, and has an experimental ?module feature for using ES6 imports directly.
  • Even npm is in on it! tink is their take on this, eliminating even Node.js from the equation and being able to both import and require dependencies without even having a node_modules directory.

The post Next Genpm appeared first on CSS-Tricks.

The Good, The Bad, And The Ad: How To Deal With Bad Mobile Ads

Usability Geek - Wed, 03/27/2019 - 11:50am
Mobile ads are part of many apps’ monetisation strategy. However, there are good mobile ads, and there are bad mobile ads. The last thing you want to see over your morning cup of coffee is this...
Categories: Web Standards

Better Than Native

Css Tricks - Wed, 03/27/2019 - 9:47am

Andy Bell wrote up his thoughts about the whole web versus native app debate which I think is super interesting. It was hard to make it through the post because I was nodding so aggressively as I read:

The whole idea of competing with native apps seems pretty daft to me, too. The web gives us so much for free that app developers could only dream of, like URLs and the ability to publish to the entire world for free, immediately.

[...] I believe in the web and will continue to believe that building Progressive Web Apps that embrace the web platform will be far superior to the non-inclusive walled garden that is native apps and their app stores. I just wish that others thought like that, too.

Andy also quotes Jeremy Keith making a similar claim to bolster the point:

If the goal of the web is just to compete with native, then we’ve set the bar way too low.

I entirely agree with both Andy and Jeremy. The web should not compete with native apps that are locked within a store. The web should be better in every way — it can be faster and more beautiful, have better interactions, and smoother animations. We just need to get to work.

The post Better Than Native appeared first on CSS-Tricks.

Breaking CSS Custom Properties out of :root Might Be a Good Idea

Css Tricks - Wed, 03/27/2019 - 4:54am

CSS Custom Properties have been a hot topic for a while now, with tons of great articles about them, from great primers on how they work to creative tutorials to do some real magic with them. If you’ve read more than one or two articles on the topic, then I’m sure you’ve noticed that they start by setting up the custom properties on the :root about 99% of the time.

While putting custom properties on the :root is great for things that you need to be available throughout your site, there are times when it makes more sense to scope your custom properties locally.

In this article, we’ll be exploring:

  • Why we put custom properties on the :root to begin with.
  • Why global scoping isn’t right for everything.
  • How to overcome class clashing with locally scoped custom properties
What’s the deal with custom properties and :root?

Before we jump into looking at the global scope, I think it’s worth looking at why everyone sets custom properties in the :root to begin with.

I’ve been declaring custom properties on the :root without even a second thought. Pretty much everyone does it without even a mention of why — including the official specification.

When the subject of :root is actually breached, it mentions how :root is the same as html, but with higher specificity, and that’s about it.

But does that higher specificity really matter?

Not really. All it does is select html with a higher specificity, the same way a class selector has higher specificity than an element selector when selecting a div.

:root { --color: red; } html { --color: blue; } .example { background: var(--color); /* Will be red because of :root's higher specificity */ }

The main reason that :root is suggested is because CSS isn’t only used to style HTML documents. It is also used for XML and SVG files.

In the case of XML and SVG files, :root isn’t selecting the html element, but rather their root (such as the svg tag in an SVG file).

Because of this, the best practice for a globally-scoped custom property is the :root. But if you’re making a website, you can throw it on an html selector and not notice a difference.

That said, with everyone using :root, it has quickly become a “standard.” It also helps separate variables to be used later on from selectors which are actively styling the document.

Why global scope isn’t right for everything

With CSS pre-processors, like Sass and Less, most of us keep variables tucked away in a partial dedicated to them. That works great, so why should we consider locally scoping variables all of a sudden?

One reason is that some people might find themselves doing something like this.

:root { --clr-light: #ededed; --clr-dark: #333; --clr-accent: #EFF; --ff-heading: 'Roboto', sans-serif; --ff-body: 'Merriweather', serif; --fw-heading: 700; --fw-body: 300; --fs-h1: 5rem; --fs-h2: 3.25rem; --fs-h3: 2.75rem; --fs-h4: 1.75rem; --fs-body: 1.125rem; --line-height: 1.55; --font-color: var(--clr-light); --navbar-bg-color: var(--clr-dark); --navbar-logo-color: var(--clr-accent); --navbar-border: thin var(--clr-accent) solid; --navbar-font-size: .8rem; --header-color: var(--clr-accent); --header-shadow: 2px 3px 4px rgba(200,200,0,.25); --pullquote-border: 5px solid var(--clr-light); --link-fg: var(--clr-dark); --link-bg: var(--clr-light); --link-fg-hover: var(--clr-dark); --link-bg-hover: var(--clr-accent); --transition: 250ms ease-out; --shadow: 2px 5px 20px rgba(0, 0, 0, .2); --gradient: linear-gradient(60deg, red, green, blue, yellow); --button-small: .75rem; --button-default: 1rem; --button-large: 1.5rem; }

Sure, this gives us one place where we can manage styling with custom properties. But, why do we need to define my --header-color or --header-shadow in my :root? These aren’t global properties, I’m clearly using them in my header and no where else.

If it’s not a global property, why define it globally? That’s where local scoping comes into play.

Locally scoped properties in action

Let’s say we have a list to style, but our site is using an icon system — let’s say Font Awesome for simplicity’s sake. We don’t want to use the disc for our ul bullets — we want a custom icon!

If I want to switch out the bullets of an unordered list for Font Awesome icons, we can do something like this:

ul { list-style: none; } li::before { content: "\f14a"; /* checkbox */ font-family: "Font Awesome Free 5"; font-weight: 900; float: left; margin-left: -1.5em; }

While that’s super easy to do, one of the problems is that the icon becomes abstract. Unless we use Font Awesome a lot, we aren’t going to know that f14a means, let alone be able to identify it as a checkbox icon. It’s semantically meaningless.

We can help clarify things with a custom property here.

ul { --checkbox-icon: "\f14a"; list-style: none; }

This becomes a lot more practical once we start having a few different icons in play. Let’s up the complexity and say we have three different lists:

<ul class="icon-list checkbox-list"> ... </ul> <ul class="icon-list star-list"> ... </ul> <ul class="icon-list bolt-list"> ... </ul>

Then, in our CSS, we can create the custom properties for our different icons:

.icon-list { --checkbox: "\f14a"; --star: "\f005"; --bolt: "\f0e7"; list-style: none; }

The real power of having locally scoped custom properties comes when we want to actually apply the icons.

We can set content: var(--icon) on our list items:

.icon-list li::before { content: var(--icon); font-family: "Font Awesome Free 5"; font-weight: 900; float: left; margin-left: -1.5em; }

Then we can define that icon for each one of our lists with more meaningful naming:

.checkbox-list { --icon: var(--checkbox); } .star-list { --icon: var(--star); } .bolt-list { --icon: var(--bolt); }

We can step this up a notch by adding colors to the mix:

.icon-list li::before { content: var(--icon); color: var(--icon-color); /* Other styles */ } Moving icons to the global scope

If we’re working with an icon system, like Font Awesome, then I’m going to assume that we’d be using them for more than just replacing the bullets in unordered lists. As long as we're using them in more than one place it makes sense to move the icons to the :root as we want them to be available globally.

Having icons in the :root doesn’t mean we can’t still take advantage of locally scoped custom properties, though!

:root { --checkbox: "\f14a"; --star: "\f005"; --bolt: "\f0e7"; --clr-success: rgb(64, 209, 91); --clr-error: rgb(219, 138, 52); --clr-warning: rgb(206, 41, 26); } .icon-list li::before { content: var(--icon); color: var(--icon-color); /* Other styles */ } .checkbox-list { --icon: var(--checkbox); --icon-color: var(--clr-success); } .star-list { --icon: var(--star); --icon-color: var(--clr-warning); } .bolt-list { --icon: var(--bolt); --icon-color: var(--clr-error); } Adding fallbacks

We could either put in a default icon by setting it as the fallback (e.g. var(--icon, "/f1cb")), or, since we’re using the content property, we could even put in an error message var(--icon, "no icon set").

See the Pen
Custom list icons with CSS Custom Properties
by Kevin (@kevinpowell)
on CodePen.

By locally scoping the --icon and the --icon-color variables, we’ve greatly increased the readability of our code. If someone new were to come into the project, it will be a whole lot easier for them to know how it works.

This isn’t limited to Font Awesome, of course. Locally scoping custom properties also works great for an SVG icon system:

:root { --checkbox: url(../assets/img/checkbox.svg); --star: url(../assets/img/star.svg); --baby: url(../assets/img/baby.svg); } .icon-list { list-style-image: var(--icon); } .checkbox-list { --icon: checkbox; } .star-list { --icon: star; } .baby-list { --icon: baby; } Using locally scoped properties for more modular code

While the example we just looked at works well to increase the readability of our code — which is awesome — we can do a lot more with locally scoped properties.

Some people love CSS as it is; others hate working with the global scope of the cascade. I’m not here to discuss CSS-in-JS (there are enough really smart people already talking about that), but locally scoped custom properties offer us a fantastic middle ground.

By taking advantage of locally scoped custom properties, we can create very modular code that takes a lot of the pain out of trying to come up with meaningful class names.

Let’s um, scope the scenario.

Part of the reason people get frustrated with CSS is that the following markup can cause problems when we want to style something.

<div class="card"> <h2 class="title">This is a card</h2> <p>Lorem ipsum dolor sit, amet consectetur adipisicing elit. Libero, totam.</p> <button class="button">More info</button> </div> <div class="cta"> <h2 class="title">This is a call to action</h2> <p>Lorem, ipsum dolor sit amet consectetur adipisicing elit. Aliquid eveniet fugiat ratione repellendus ex optio, ipsum modi praesentium, saepe, quibusdam rem quaerat! Accusamus, saepe beatae!</p> <button class="button">Buy now</button> </div>

If I create a style for the .title class, it will style both the elements containing the .card and .cta classes at the same time. We can use a compound selector (i.e. .card .title), but that raises the specificity which can lead to less maintainability. Or, we can take a BEM approach and rename our .title class to .card__title and .cta__title to isolate those elements a little more.

Locally scoped custom properties offer us a great solution though. We can apply them to the elements where they’ll be used:

.title { color: var(--title-clr); font-size: var(--title-fs); } .button { background: var(--button-bg); border: var(--button-border); color: var(--button-text); }

Then, we can control everything we need within their parent selectors, respectively:

.card { --title-clr: #345; --title-fs: 1.25rem; --button-border: 0; --button-bg: #333; --button-text: white; } .cta { --title-clr: #f30; --title-fs: 2.5rem; --button-border: 0; --button-bg: #333; --button-text: white; }

Chances are, there are some defaults, or commonalities, between buttons or titles even when they are in different components. For that, we could build in fallbacks, or simply style those as we usually would.

.button { /* Custom variables with default values */ border: var(--button-border, 0); /* Default: 0 */ background: var(--button-bg, #333); /* Default: #333 */ color: var(--button-text, white); /* Default: white */ /* Common styles every button will have */ padding: .5em 1.25em; text-transform: uppercase; letter-spacing: 1px; }

We could even use calc() to add a scale to our button, which would have the potential to remove the need for .btn-sm, btn-lg type classes (or it could be built into those classes, depending on the situation).

.button { font-size: calc(var(--button-scale) * 1rem); /* Multiply `--button-scale` by `1rem` to add unit */ } .cta { --button-scale: 1.5; }

Here is a more in-depth look at all of this in action:

See the Pen
Custom list icons with CSS Custom Properties
by Kevin (@kevinpowell)
on CodePen.

Notice in that example above that I have used some generic classes, such as .title and .button, which are styled with locally scoped properties (with the help of fallbacks). With those being setup with custom properties, I can define those locally within the parent selector, effectively giving each its own style without the need of an additional selector.

I also set up some pricing cards with modifier classes on them. Using the generic .pricing class, I set everything up, and then using modifier classes, I redefined some of the properties, such as --text, and --background, without having to worry about using compound selectors or additional classes.

By working this way, it makes for very maintainable code. It’s easy to go in and change the color of a property if we need to, or even come in and create a completely new theme or style, like the rainbow variation of the pricing card in the example.

It takes a bit of foresight when initially setting everything up, but the payoff can be awesome. It might even seem counter-intuitive to how you are used to approaching styles, but next time you go to create a custom property, try keeping it defined locally if it doesn’t need to live globally, and you’ll start to see how useful it can be.

The post Breaking CSS Custom Properties out of :root Might Be a Good Idea appeared first on CSS-Tricks.

Google to offer Android users browser choice

QuirksBlog - Thu, 03/21/2019 - 5:17am

Yesterday the European Commission fined Google for almost €1.5 billion for unfairly favoring some of its online advertising services over those of its rivals — and it appears the EC isn’t done yet.

One of the ongoing antitrust cases is about Android, and more specifically about Google Services, the package of Google apps such as Play, YouTube, and Chrome that Android-using hardware vendors must either adopt completely, or not at all.

Getting Google Play on their devices requires vendors to adopt Services. That is the reason that almost all non-Chinese Android phones come with Google Chrome installed, even if they have another browser, such as Samsung Internet, on the home screen.

Browser choice

If Google Services is ruled in contravention of EU antitrust rules, that may have an impact on the Android browser market. Google itself sees that as well, and is taking measures. Yesterday, it stated in a press release:

Now we’ll also do more to ensure that Android phone owners know about the wide choice of browsers and search engines available to download to their phones. This will involve asking users of existing and new Android devices in Europe which browser and search apps they would like to use.

(Haven’t we heard this before? Indeed.)

Apparently, the European Commission wants Google to clarify that users can download other browsers. Although this is a good idea when it comes to diversifying the browser market, there are several knotty problems that I don’t see an easy solution for.

To be fair to Google, Android has always allowed consumers to install any browser they like, and using any browser they can access any search engine they like. (So could Windows users, back in the day.)

Also, the average consumer doesn’t care about browsers. On Samsung devices some users (about 30-40%?) use Samsung Internet over Google Chrome, but that’s only because Samsung Internet is on the home screen and Google Chrome is not.

Browser choice screens

Still, it seems European Android users will get a browser choice screen similar to what we saw ten years ago.

We only have to make the old choice screen responsive, and it’s ready for roll-out. That responsive bit is important: the browser that ends up at the top of the list will likely be selected far more often than the others. Most consumers don’t really care about the choice they’re being given, and a tap is easier than a scroll and tap. Therefore, a random order of browsers seems likely, just like ten years ago.

But which browsers will be selected for the browser screen? Ten years ago it was clear: IE, Firefox, Chrome, Safari, and Opera.

Right now the situation is much less clear. Let’s see:

  • Google Chrome, Opera Mobile, Samsung Internet, and Firefox should be on the list for sure.
  • Any other vendor-created Chromium browser? I’m not sure which ones there are right now, and they’ll likely be restricted to the devices of their vendor, but as long as we’re being inclusive they should be on the list where possible.
  • UC? Yes in principle, but it’s a bit odd for Europeans, who’ve never heard of it.
  • QQ, or however the TenCent browser is called nowadays? Same problem.
  • Opera Mini? The average consumer has no idea what a proxy browser is and will get confused. (The average web developer hasn’t, either, and will, too.)
  • Puffin? Too weird.

Besides, who’ll take the decision which browsers to include? Google, most likely, though it is restrained by the EC’s cold staring antitrust eyes in its back. Then again, the EC doesn’t know anything about browsers.

And what if the device’s browser is already something other than Google Chrome? In theory the choice screen would not be necessary there. (Ten years ago Microsoft only offered the choice screen on new computers. But Google explicitly said “existing and new Android devices.”)

And what about WebViews? Here Google’s monopoly is even bigger than with the Google Chrome browser, since there is no choice whatsoever under the Google Services agreement. An extra browser, sure, that’s allowed. A new WebView is not: you must use the Google-provided Chrome.

So there are plenty of detail questions that I dont’t know the answer to. Worse, I’m suspecting Google and the EC don’t, either.

The result

What will the result be? As far as I can recall, when Microsoft offered users a choice ten years ago, not all that much changed in the browser market. Still, we have to consider the possibility of a minor mobile browser market shake-up in Europe.

So let’s make a note of the February 2019 mobile browser market in Europe according to StatCounter:

  1. Google Chrome: 59.7%
  2. Safari iOS: 26.2%
  3. Samsung Internet: 10.3%
  4. Other: 3.8%

Let’s revisit this in a while and see if anything has changed. Google wasn’t very clear on when the choice screen would be offered, but I expect it to be somewhere in the next year or so.

But I am not expecting a lot from this initiative — and I suspect that’s exactly why Google is offering it. Still, this episode serves to highlight that dominance in the browser market has now passed to Chrome, and that from a diversity point of view it would be a good idea to do something about that.

The elephant in the room

Finally, we’re left with one elephant in the room: iOS. Contrary to Android, iOS does not allow the installation of other rendering engines. Isn’t that a much worse monopoly than the one Google has over Android? Shouldn’t Apple, too, be forced to give consumers choice?

Scope in CSS

QuirksBlog - Tue, 03/19/2019 - 2:53am

I am likely going to write a “CSS for JavaScripters” book, and therefore I need to figure out how to explain CSS to JavaScripters. This series of article snippets are a sort of try-out — pre-drafts I’d like to get feedback on in order to figure out if I’m on the right track.

Today we treat the knotty problem of CSS selector scope. JavaScripters rightly feel that the fact that all CSS selectors are in the global scope complicates their applications. What can we do about it?

I wrote the explainer below. As usual, I’d love to hear if this explainer works for you or confuses you.

Global scope

Any CSS selector is valid throughout the document. If you use p span it selects any span in a p in the entire document. Here, every span in a p in the document has a red background.

p span { background-color: red; }

Sometimes you don’t want that. Sometimes you want to select only spans in ps in your specific module. This is the core of the scope problem in CSS: how to restrict your style definitions to only the module you’re working on.

The fundamental solution is adding a class name or ID before the actual selector; something like #myModule p span. Now the declaration is scoped to the myModule element.

In this code example, spans in ps are red, except when they’re in the myModule element; then they’re blue.

#myModule { border: 1px solid black; padding: 1em; } p span { background-color: red; } #myModule p span { background-color: blue; }

Yes, scoping sort-of works, but your CSS file becomes a jumbled mess of selectors, overrules, and other stuff. For intance, where exactly do you put the #myModule p span rule? I always place it after the global selector it overrules, as in the example above, but I can see why people would set it straight after #myModule. Fun times ahead when you’re taking over someone else’s CSS.

Scoping CSS selectors with sane, readable syntax is one of the purposes of the many CSS-in-JS solutions that are now vying for developer attention. (Another purpose is making sure that scoping IDs aren’t repeated — if your HTML contains two elements with id="myModule" you have the same scoping problem all over again.)

However, it appears that the CSS scoping problem will be solved in the not-too-distant future. A limited local scope is already present, and a full solution is in the making.

CSS custom properties

CSS custom properties (also called CSS variables) already have scope. It is possible to redefine the value of a custom property for a specific element and its descendants.

Take this example:

body { --color: red; } #myModule { border: 1px solid black; padding: 1em; --color: blue } p span { background-color: var(--color); }

Now a span in a p has a red background, except in myModule, where it has a blue background. In practice, the html and body elements count as the global scope; most other elements as a local scope.

Custom properties can hold any valid CSS value, and they work for any declaration. So we could extend the example like this:

body { --color: red; --spandisplay: inline; } #myModule { border: 1px solid black; padding: 1em; --color: blue --spandisplay: block; } p span { background-color: var(--color); display: var(--spandisplay); }

Now spans in ps in myModule have display: block, while spans in ps elsewhere have display: inline.

There is no doubt that true local scope has landed in CSS with the addition of custom properties. There is also no doubt that the system can be clunky when you want to use local scoping on a massive scale.

In theory it’s possible to define a gazillion custom properties in myModule for internal use, and define the same properties with different values in otherModule. However, this assumes that, internally, the modules will have the same structure. For instance, the simple example above assumes that every module in the entire page uses p span in a similar way. If otherModule would use p strong instead, you’d have to add new declarations. All this is not impossible, but it’s questionable whether it solves CSS’s scoping problem in an easy-to-use way.

So all in all the verdict is mixed. Yes, custom properties bring local scope to CSS, but it’s best used in small, subtle ways instead of the wholesale, system-wide way JavaScripters would like to see. [Unless I’m missing something here. If I do, please tell me. I need to know.]

CSS nesting

The CSS Nesting specification offers a new way of sort-of creating sort-of local CSS selectors. Note that this spec is relatively new, and it will take a little while before browsers support it.

CSS preprocessors have done nesting for ages now, and the proposed syntax is quite close to SASS:

p span { background-color: red; /* display: inline is the default anyway; no need to define it */ } #myModule { border: 1px solid black; padding: 1em; & p span { background-color: blue; display: block; } }

The & p span evaluates to #myModule p span; in other words, the & adds the parent selector. Note that the & is required: CSS needs to know where to insert the parent selector.

On the one hand, CSS Nesting offers syntactic sugar, but nothing fundamentally new. We already saw how to write the example above in today’s CSS:

On the other hand, the nested variant is much more readable, and offers you a simple way of stating whether a certain selector is local or global. It is totally clear that & p span is a local selector, and that its styles will not apply outside myModule. The p span outside the block, on the other hand, is clearly global.

This makes it a lot easier to see the scope of your selectors at a glance, and to subdivide your CSS files. If you’re working on myModule, you add styles to the myModule block. If you define styles outside that block, it’s clear that they are global.

Would CSS nesting help?

Today’s question to JavaScripters is: do you think that CSS Nesting will make your work significantly easier? It seems so to me, but I am an old-guard front-end developer with little knowledge of the modern JavaScript ecosystems, so I might miss something.

if statements and for loops in CSS

QuirksBlog - Wed, 03/13/2019 - 4:12am

I am likely going to write a “CSS for JavaScripters” book, and therefore I need to figure out how to explain CSS to JavaScripters. This series of article snippets are a sort of try-out — pre-drafts I’d like to get feedback on in order to figure out if I’m on the right track.

Today I continue to look at CSS as a programming language. The question whether it is one or not is a very hot topic right now, but I’m not terribly interested in the answer.

Instead, I’d like to know if describing certain CSS structures in programming terms helps you learn CSS better or quicker, or if it hinders you. In other words, is there any educational value in treating CSS as a programming language?

Please tell me if the explanation below is helpful or confusing to you.

if statements

An area where the CSS programming language is less developed than JavaScript is control structures — or so it would seem.

Still, CSS has if statements. Here are a few examples:

@media all and (max-width: 900px) { } @supports (display: flex) { }

These mean “if the layout viewport is at most 900px wide” and “if the CSS engine accepts display: flex.” There is no doubt that these are actual if statements: the code blocks are only applied if the condition is true. (Also, the specification for @media and @supports is called CSS Conditional Rules. That’s a dead giveaway: at-rules are meant to be if statements.)

But let’s take a look at a — dare I say it? — more iffy example. Is the following also an if statement?

menu a { color: red; }

“If there is a link within a menu, make it red.” Several people I interviewed for the book were passionate in their belief that selectors are if statements as well.

Do you agree? Do I agree? I’m not sure, although I do see the point: it is possible to see selectors as such. Whether you consider them true if statements probably depends on your definition of an if statement.

for loops

Let’s make things slightly more complicated by considering for loops. Now at first sight it would appear CSS doesn’t have any. Still, what about the same bit of code we saw above?

menu a { color: red; }

In a way, a selector like the one above could be considered a primitive for-loop. The browser is told to loop through all <a> elements inside a <menu> element and apply a red colour.

Is a selector a for loop? Can it even be an if statement and for loop at the same time? Again, this depends on your definitions of for loops and if statements.

I’d like to mention in passing that it is possible to add extra logic to CSS for loops.

menu a:first-child { color: blue; } menu a:not(#current) { color: red; }

These extra selectors can be treated as if statements within a for loop: go through all links in a menu, but skip this one and give that one special treatment.

Declarative vs imperative

Let’s take the most expansive view and say that CSS selectors can be considered both if statements and for loops. That will sound fairly weird for anyone with a background in JavaScript, since these two types of control structures are simply not the same. So how can you replace both by a single structure?

Here, I think, we once again see that CSS is a declarative language, and not an imperative one. In declarative languages some simple control structures can be expressed much more succinctly than in imperative ones.

Take the last code example above. In JavaScript we’d have to say something like:

for (all menus) { for (all links in this menu) { let first = [figure out if this is the first link in the menu] if (first) { link.color = 'blue' } else if (link.id !== 'current') { link.color = 'red'; } } }

The drawback of the JavaScript version is that it’s more verbose than the CSS version, and hence more prone to error. The advantage is that it offers much finer control than CSS. In CSS, we’ve just about reached the limits of what we can express. We could add a lot more logic to the JavaScript version, if we wish.

In CSS, we tell the browser how links should look. In JavaScript, we describe the algorithm for figuring out how an individual link should look. Neither is wrong, but in this example the CSS way is the more efficient way.

Personally, I’m fine with seeing CSS selectors as if statements and for loops at the same time. However, I feel that once you start understanding CSS, the fact that selectors are ifs/fors becomes less and less relevant. Instead, selectors are just selectors: great for relatively simple declarations; less so for very complex ones.

Helpful or confusing?

If you’re a JavaScripter who’d like to get to know CSS better I’d love to hear if the few examples above are helping or confusing you. The more feedback I get, the better I can write a book that helps you learn CSS instead of just confusing you.

Thanks.

Feedback

Badly formatted

See also https://csswizardry.com/2015/04/cyclomatic-complexity-logic-in-css/

See also https://adactio.com/journal/14574

I did a presentation about this topic at AmsterdamJS, and the feedback I got made me conclude that this approach is not really suited for learning CSS. Everybody understood my point, but most thought it didn't really help them understand CSS better. So this is going to become a sidebar in the book, and not main text.

Wed, 12/31/1969 - 2:00pm
Syndicate content
©2003 - Present Akamai Design & Development.