Use Push Notifications to Build Repeat Traffic

Use Push Notifications to Build Repeat TrafficTo engage your audience, you’ll have to be able to capture their attention in meaningful ways. This isn’t always an easy task, however, especially when there are so many distractions on their mobile devices. Fortunately, push notifications offer an effective solution. Push notifications are a way for publishers and other businesses to deliver direct, real-time […]

The post Use Push Notifications to Build Repeat Traffic appeared first on WPExplorer.

ExpressionEngine Under New Ownership, Will Remain Open Source for Now

EllisLab founder Rick Ellis announced yesterday that ExpressionEngine has been acquired by Packet Tide, the parent company of EEHarbor, one of the most successful EE add-on providers and development agencies in the community. A year ago EllisLab, the developers of EE core, was acquired by Digital Locations but Ellis said the company ended up not being a good fit for the future of the CMS:

A year ago, EllisLab was acquired by Digital Locations in order to facilitate the transition of ExpressionEngine from a commercial software application to an open source one. That transition was successful, but it became apparent in recent months that ExpressionEngine didn’t fit perfectly within the goals of Digital Locations, as it seeks to build a business in Artificial Intelligence.

We decided that what was best for ExpressionEngine was to seek a new owner, one that could devote all the resources necessary for ExpressionEngine to flourish.

In November 2018, EE went open source, adopting the Apache License Version 2.0, after 16 years of being locked down under restrictive licensing. EE’s dwindling community of product developers and site builders were hopeful that the new open source licensing would expand EE’s reach and bring back developers who had migrated to alternatives like Craft.

After the acquisition announcement, the EE community was concerned whether or not it will remain free and open source. Although the software’s homepage sports the tagline “The Open-Source CMS that supports YOU all the way,” EE’s new owners have left the option open for reconsidering its licensing further down the road. They plan to stick with the open source license for the time being. When asked directly in the EE Slack, EE Harbor developer Tom Jaeger said, “That is our plan for now, although at this stage we’re looking at everything with a fresh eye towards what’s best.” The company has published a list of FAQs with the same information.

Brian Litzinger, a developer at BoldMinded, who has created more than 36 add-ons for EE, and is also on the EECA (ExpressionEngine Community Association) board that organizes EEConf, said he has confirmed that EEHarbor plans to keep the CMS open source.

“The board spoke to new ownership just today actually, and they have every intention of keeping it open source,” Litzinger said. “I can’t speak for the whole community, but since going open source my add-on sales have not significantly increased or decreased.

“As with any open source project there has been feedback and pull requests from the community, but nothing significant (e.g. large features). The community as a whole is pretty excited about the new ownership and ExpressionEngine’s future though.”

Shawn Maida, founder of Foster Made, a company that also sells ExpressionEngine add-ons, said he has not seen a significant direct change in the economics of EE since the project went open source.

“I think the real question here is what business model best enables the growth and continued support of the CMS itself, and how is that balanced against the growth of the community,” Maida said. “As a business that offers some add-ons for ExpressionEngine, we need to see both continued growth in ExpressionEngine as a platform and growth in the community, so I think the license model that best enables that matters.”

Travis Smith, president of Hop Studios, has been working with EE since its early days. As someone who is deeply invested in the EE community, he said that he doesn’t think a prospective licensing change would impact the broader community as much as having a clear vision for the CMS’s future.

“I think a licensing change per se wouldn’t be good or bad, but a well-articulated and communicated vision for the CMS’s future would be really helpful for a community that feels unsure at the moment,” Smith said.

“I do think that the exposure that going open source gave into the development process overall at EllisLab was an improvement, and that new features and bug fixes were getting added at a decent pace.”

EE may have changed its licensing to be open source but it is not a community-led project where major decisions happen by a consensus of a diverse representation of community leadership.

“I didn’t observe the community gaining (or applying?) much input or influence over the future of ExpressionEngine in the past year,” Smith said. “I think there was still a feeling of ‘EE is EllisLab’s project’ — and that this change of ownership might shake the community’s devs out of that default assumption, which would be a good thing.”

In the FAQs EEHarbor published today, the company confirmed that it will be developing new features and that it will consider feedback submitted from the community:

While we are in the early stages of long-term strategic planning, we already have a lot of thoughts and ideas around where to take ExpressionEngine based on our own experience. However, it’s not just about us. We are also very interested in collaborating with the ExpressionEngine community. Everyone is more than welcome to submit feedback for us to review as we consider the future of ExpressionEngine

After 16 years under a restrictive license, EE is an interesting example of a newly open source, corporate-led project with a community that is rediscovering its place while ownership of the software is transferred from one company to another. Responses to the acquisition are mostly positive, and users seem excited about Packet Tide’s first planned initiative – finishing development on ExpressionEngine 6.0. Ellis described this upcoming release as “an exciting new version we’ve been quietly working on behind the scenes.” It will include a new control panel with a dark theme, along with add-on and service integrations inside the app.

EEHarbor does not plan to merge its add-ons with ExpressionEngine core at this time, and the statement published today reiterates the company’s commitment to “keep the add-on marketplace fair and open to all developers.”

C++: how can print in same column?

how can i print 3 values(without knowing their string\number size) in same column using cout?
i'm using these code:

cout <<"\n" << "show tokens\n";
        for(unsigned int i=0;i<Tokens.size(); i++)
        {
            cout << "Token: " << Tokens[i].Token <<right<<setw(20-Tokens[i].Token.size())<< "Type: " << Tokens[i].Type <<setw(40) << fixed << "Position Line: " << i<<"\n";
        }

but i know the 'token' size, but not the type size. so what you can advice me?

Blocking Third-Party Hands from the Cookie Jar

Third-party cookies are set on your computer from domains other than the one that you're actually on right now. For example, if I log into css-tricks.com, I'll get a cookie from css-tricks.com that handles my authentication. But css-tricks.com might also load an image from some other site. A common tactic in online advertising is to render a "tracking pixel" image (well named, right?) that is used to track advertising impressions. That request to another site for the image (say, ad.doubleclick.com) also can set a cookie.

Eric Lawrence explains the issue:

The tracking pixel’s cookie is called a third party cookie because it was set by a domain unrelated to the page itself.

If you later visit B.textslashplain.com, which also contains a tracking pixel from ad.doubleclick.net, the tracking pixel’s cookie set on your visit to A.example.com is sent to ad.doubleclick.net, and now that tracker knows that you’ve visited both sites. As you browse more and more sites that contain a tracking pixel from the same provider, that provider can build up a very complete profile of the sites you like to visit, and use that information to target ads to you, sell the data to a data aggregation company, etc.

But times are a changin'. Eric goes on to explain the browser landscape:

The default stuff is the big deal, because all browsers offer some way to block third-party cookies. But of course, nobody actually does it. Jeremy:

It’s hard to believe that we ever allowed third-party cookies and scripts in the first place. Between them, they’re responsible for the worst ills of the World Wide Web.

2019 is the year we apparently reached the breaking point.

The post Blocking Third-Party Hands from the Cookie Jar appeared first on CSS-Tricks.

Rosa 2 Restaurant Theme Provides a Frustrating and Satisfying Experience

Screenshot of the Rosa 2 restaurant WordPress theme.

Rosa 2 is the sequel to Pixelgrade’s best-selling theme, Rosa. The new theme re-imagines its previous incarnation in the context of the block editor (Gutenberg). I was provided a copy of the theme for free to test and provide my thoughts.

The theme sells for $75/year, or you can pay a one-time fee of $95 for lifetime access. The product launch post could make anyone excited about this theme, but is it worth it?

TLDR; Rosa 2 made for a satisfying experience when building restaurant-style pages. However, the early learning curve and basic setup were frustrating. It also lacks some of the polish I’d expect at a premium price.

A Rundown of the Issues

Before I dive into the good things about Rosa 2 (and there are some nice things about this theme), let me dive into the frustrating aspects. There were so many pain points that I nearly gave up on the theme several times. However, I soldiered on in the hopes of understanding why this theme might be worth using.

Install the Required Plugins First

Let me save you some time right now. When the theme says that it requires the Customify and Nova Blocks plugins, it truly requires them. Otherwise, the theme looks and behaves nothing like the demo or screenshots. It may as well not be the same theme.

When first activating the theme, the front page of your website will become a completely white screen. It is not the dreaded White Screen of Death caused by an error. Instead, the theme is forcibly hiding the content with custom styles.

Why? Yeah, good question.

I see no reason to do so. Outside of changing some code (which I did), users must activate the plugins to make their content appear. There is no technical reason this should be the case when using this theme.

There should be no path in which a user installs a theme only to have their content disappear.

I get it. I was told these were required plugins. The theme even provides easy installation and activation links via the TGM Plugin Activation script. I also get that WordPress lacks any sort of real dependency system for handling this feature. That doesn’t make it any less of a poor user experience.

As a developer, I thought I’d trick the system and test the theme without those plugins installed. I wanted to see what the theme looked like out of the box, which you can see in the following screenshot.

Rosa 2 default homepage output.

Oh, and that big block of category links in the above screenshot, it never goes away. It just sits there on your blog posts page. It is hard-coded in the posts page template (home.php). Rosa 2 is billed as a restaurant theme, so it might be acceptable if you don’t plan on running a blog.

Header and Nav Problems

The default header looks nothing like the screenshots, demo, or video for the theme. After nearly two hours of using the theme, I was ready to throw in the towel and rule this theme out as a lost cause. Not being able to get the basic nav menu set up for the theme was an exercise in self-punishment that I wouldn’t wish on anyone.

It turns out that the Nova Blocks plugin really is required. Did I mention that you should install the required plugins first?

Stretched images

On blog and archive pages, expect stretched featured images that attempt to fill out the box next to the excerpt for existing posts. There doesn’t seem to be any remedy to this outside of uploading new images.

The theme uses the standard post-thumbnail size but does not define this size in the code. For those unfamiliar with the technical aspects when using this specific size, the theme should ideally define it via the set_post_thumbnail_size() function.

Sticky header

The large sticky header gave me a gut-wrenching feeling that walls were closing in on me. I became light-headed and dizzy. I found it tough to breathe. This is not hyperbole. I’m dead serious.

On a personal note, I’ve had some issues with claustrophobia for the last couple of years. I first had this feeling after being stuck indoors for two weeks while watching over one of my cats who had surgery. I typically work from the porch where I can get fresh air, but that was one of the worst periods of my life.

Since then, I often get this same feeling when sites have large sticky headers. It feels like the walls are closing down. I wonder if others have similar issues.

This feeling could be alleviated if the theme minimized the sticky-header height while scrolling down the page. Fortunately, the theme allows users to choose a static header, which I strongly suggest using. There are some other spacing and sizing options for the header area, which can help shrink some of this down.

Where the Theme Shines

Custom restaurant-style page created with the Rosa 2 theme.

If there is one thing this theme does well, it is making it simple to create pages for a restaurant via the Nova Blocks plugin. Within minutes of creating a custom page, I had a restaurant-style page set up and ready to go.

When coupled with Nova Blocks, the theme beautifully handles the process of creating custom pages with numerous unique outcomes. The integration with the plugin is brilliant. Each block has custom demo content that you can easily modify.

Some of the names of the blocks and block options were cutesy and fun, such as “Hero of the Galaxy,” but they became a slight nuisance when wanting to quickly figure out the purpose of a block. I could see some users becoming annoyed at the names, and they might not be ideal for some professional settings. They were kind of fun though. I have mixed feelings about them.

How Does the Theme Handle Gutenberg?

Screenshot of the Rosa 2 theme when used in the Gutenberg editor.

Rosa 2 is a theme primarily built for the block editor. It wonderfully handled core block output in my tests.

When using Gutenberg-ready themes, I view the pullquote block as sort of the theme designer’s signature. It is one of those blocks where designers can have a lot of fun and put a unique spin on the display. I’m a fan of the pullquote style in this theme (pictured above).

On the whole, it works well. When coupled with Nova Blocks, you have a lot of power at your disposal.

How Does the Code Stack Up?

Rosa 2 is lightweight in terms of custom code. Nearly all of the functionality is within the accompanying plugins. Because this is a theme review, I didn’t dive into the plugin code.

From a purely technical standpoint, the theme does most things according to standards.

There are some things I’d change from an architectural standpoint. For example, the file for its Customify plugin integration is over 1,100 lines of code. I would break that down to more digestible bits, which would help with long-term maintenance and bug hunting.

Some of the editor-related JavaScript code could be more efficient. Repeated patterns should be grouped together to make the code smaller. The editor JavaScript file is not large, but every byte counts in a world where developers assume everyone is running on Gigabit internet connections.

The primary stylesheet is 173 kb, which is OMGBBQ large, especially when you top it off with 100s of kb coming from the stylesheets and scripts loaded by Nova Blocks plugin. Unless you’re a user who is heavily optimizing your site, you can count on some slow page loads.

The Final Verdict

I’d only recommend this theme to people who have more patience than me. While I didn’t follow instructions right off the bat (as a reviewer, I’m trying to push limits and break things), the theme did have some pain points that simply made for a frustrating process.

I’m in the camp of people who believes themes should work out of the box. This theme doesn’t work without some setup. You’ll need to put in some legwork to get it going. However, once you make it over the initial hump, you can build some beautiful page layouts.

I suggest using it strictly for its defined purpose of building a restaurant website. The typography is designed well enough for blogging, but the overall theme isn’t well-suited to it.

Build a RingCentral Virtual Voicemail Assistant for Your Business   — Part 1

RingCentral Virtual Voicemail Assistant

Nowadays, consumers have a variety of options for obtaining services and getting the help they need. They can use webchat, email, the Internet, and face-to-face contact, yet telephone customer service is still the first choice for most customers when they have questions or a problem that needs to be resolved.

In order to ensure your customers are happy with the customer service they receive, it’s even more important for you to provide exceptional customer service, including outstanding telephone service. Consumers expect better service than ever before, and the capabilities of modern telephone communications allow you to offer them the satisfaction and resolution they demand.

#241: CTO

Show Description

Chris talks with Alex about his role as CTO at CodePen and what he sees as his job, how to learn from mistakes, and ways to level up as a developer.

Time Jumps

  • 03:48 Why the need for a CTO?
  • 11:58 Sponsor: Stackbit
  • 12:37 Building developer happiness
  • 15:19 Why don't we just build a feature and slap it out there?
  • 18:43 Learning from mistakes and issues
  • 30:26 How to level up as a developer

Sponsor: Stackbit

Static sites and the JAMStack are growing fast. Front-end devs already get it. It's fast, secure and as a developer, you get full control over the markup and the design.

Stackbit lets you build and deploy a full JAMstack site, with an SSG and headless CMS in just a few clicks. You can already choose from about a dozen prebuilt themes for Hugo, Jekyll and Gatsby and connect to Forestry, NetlifyCMS, DatoCMS or Contentful. It all happens right in your own repo.

On top of that, Stackbit just released custom themes.

Use the link stackbit.com/codepen, feel the magic, and let us know what you think.

Show Links

CodePen Links

The post #241: CTO appeared first on CodePen Blog.

The Best of Node and Express [Articles and Tutorials]

All aboard!

Built on top of Google Chrome's V8 Engine, Node.js (and its companion framework, Express.js) have come to dominate much of backend development, especially when JavaScript is your language of choice on the server-side. In this edition of "Best of DZone," we're going to take a look into the two frameworks to better understand key pieces of functionality and how they work in tandem to create applications.  

Before we begin, we'd like need to thank those who were a part of this article. DZone has and continues to be a community powered by contributors like you who are eager and passionate to share what they know with the rest of the world. 

Automated Root-Cause Analysis

When we look at the process of creating large-scale enterprise software projects, bugs are inevitable like the sun over the Sahara Desert.

The final stage of the Software Development Life Cycle (SDLC) is Post-Mortem, which includes the analysis of the process and the enhancements of the SDLC. In Russell Ovans' book, Lord of Files: Essays on the Social Aspects of Software Engineering, the author explains how the software development life cycle continues.

Deep Dive Into OAuth2.0 and JWT (Part 1 Setting the Stage)

Right from the inception of computer-based applications to today, one of the most common, yet complex problems that almost every developer must have come across during his career is security. Which, means understanding what data/information to be presented to whom — in addition to many other aspects like time, validation, re-validation and so on.

All the concerns related to security can be broken down into two categories. Authentication and Authorization.

Handling JSON Data in Python

I recently finished writing two assets — a Spark-based data ingestion framework and a Spark-based data quality framework; both were metadata-driven. As is typical, the behavior of the assets is stored in an RDBMS. In the data ingestion framework, I needed to store parameters for the source (information like username, password, path, format, etc), the destination (information like username, password, path, format, etc), compression, etc. In normal schemas, I have seen these parameters modeled as columns in a table.

Being a programmer at heart, I decided not to use multiple columns. Instead, all the parameters would be stored in a single column (as a string in the database table). The Spark application would have the responsibility of reading the string and extracting the required parameters.

The Easiest Way to Securely Query Postgres in Node.js

When you’re querying Postgres, you need to choose between:

  • Using an ORM. This gives you “native” feeling APIs to query the database.
  • Using raw SQL. This gives you the ultimate flexibility and performance and gives you more transferable skills. It’s always helpful to know how to write SQL.

Postgres ORM

If you want to use an ORM to query Postgres, I recommend using https://typeorm.io. If you’re starting with a fresh project, you can use their typeorm init CLI command:

Patterns for Practical CSS Custom Properties Use

I've been playing around with CSS Custom Properties to discover their power since browser support is finally at a place where we can use them in our production code. I’ve been using them in a number different ways and I’d love for you to get as excited about them as I am. They are so useful and powerful!

I find that CSS variables usage tends to fall into categories. Of course, you’re free to use CSS variables however you like, but thinking of them in these different categories might help you understand the different ways in which they can be used.

  • Variables. The basics, such as setting, a brand color to use wherever needed.
  • Default Values. For example, a default border-radius that can be overridden later.
  • Cascading Values. Using clues based on specificity, such as user preferences.
  • Scoped Rulesets. Intentional variations on individual elements, like links and buttons.
  • Mixins. Rulesets intended to bring their values to a new context.
  • Inline Properties. Values passed in from inline styles in our HTML.

The examples we’ll look at are simplified and condensed patterns from a CSS framework I created and maintain called Cutestrap.

A quick note on browser support

There are two common lines of questions I hear when Custom Properties come up. The first is about browser support. What browsers support them? Are there fallbacks we need to use where they aren’t supported?

The global market share that support the things we’re covering in this post is 85%. Still, it’s worth cross-referencing caniuse) with your user base to determine how much and where progressive enhancement makes sense for your project.

The second question is always about how to use Custom Properties. So let’s dive into usage!

Pattern 1: Variables

The first thing we’ll tackle is setting a variable for a brand color as a Custom Property and using it on an SVG element. We'll also use a fallback to cover users on trailing browsers.

html {
  --brand-color: hsl(230, 80%, 60%);
}

.logo {
  fill: pink; /* fallback */
  fill: var(--brand-color);
}

Here, we've declared a variable called --brand-color in our html ruleset. The variable is defined on an element that’s always present, so it will cascade to every element where it’s used. Long story short, we can use that variable in our .logo ruleset.

We declared a pink fallback value for trailing browsers. In the second fill declaration, we pass --brand-color into the var() function, which will return the value we set for that Custom Property.

That’s pretty much how the pattern goes: define the variable (--variable-name) and then use it on an element (var(--variable-name)).

See the Pen
Patterns for Practical Custom Properties: Example 1.0
by Tyler Childs (@tylerchilds)
on CodePen.

Pattern 2: Default values

The var() function we used in the first example can also provide default values in case the Custom Property it is trying to access is not set.

For example, say we give buttons a rounded border. We can create a variable — we’ll call it --roundness — but we won't define it like we did before. Instead, we’ll assign a default value when putting the variable to use.

.button {
  /* --roundness: 2px; */
  border-radius: var(--roundness, 10px);
}

A use case for default values without defining the Custom Property is when your project is still in design but your feature is due today. This make it a lot easier to update the value later if the design changes.

So, you give your button a nice default, meet your deadline and when --roundness is finally set as a global Custom Property, your button will get that update for free without needing to come back to it.

See the Pen
Patterns for Practical Custom Properties: Example 2.0
by Tyler Childs (@tylerchilds)
on CodePen.

You can edit on CodePen and uncomment the code above to see what the button will look like when --roundness is set!

Pattern 3: Cascading values

Now that we've got the basics under our belt, let's start building the future we owe ourselves. I really miss the personality that AIM and MySpace had by letting users express themselves with custom text and background colors on profiles.

Let’s bring that back and build a school message board where each student can set their own font, background color and text color for the messages they post.

User-based themes

What we’re basically doing is letting students create a custom theme. We'll set the theme configurations inside data-attribute rulesets so that any descendants — a .message element in this case — that consume the themes will have access to those Custom Properties.

.message {
  background-color: var(--student-background, #fff);
  color: var(--student-color, #000);
  font-family: var(--student-font, "Times New Roman", serif);
  margin-bottom: 10px;
  padding: 10px;
}

[data-student-theme="rachel"] {
  --student-background: rgb(43, 25, 61);
  --student-color: rgb(252, 249, 249);
  --student-font: Arial, sans-serif;
}

[data-student-theme="jen"] {
  --student-background: #d55349;
  --student-color: #000;
  --student-font: Avenir, Helvetica, sans-serif;
}

[data-student-theme="tyler"] {
  --student-background: blue;
  --student-color: yellow;
  --student-font: "Comic Sans MS", "Comic Sans", cursive;
}

Here’s the markup:

<section>
  <div data-student-theme="chris">
    <p class="message">Chris: I've spoken at events and given workshops all over the world at conferences.</p>
  </div>
  <div data-student-theme="rachel">
    <p class="message">Rachel: I prefer email over other forms of communication.</p>
  </div>
  <div data-student-theme="jen">
    <p class="message">Jen: This is why I immediately set up my new team with Slack for real-time chat.</p>
  </div>
  <div data-student-theme="tyler">
    <p class="message">Tyler: I miss AIM and MySpace, but this message board is okay.</p>
  </div>
</section>

We have set all of our student themes using [data-student-theme] selectors for our student theme rulesets. The Custom Properties for background, color, and font will apply to our .message ruleset if they are set for that student because .message is a descendant of the div containing the data-attribute that, in turn, contains the Custom Property values to consume. Otherwise, the default values we provided will be used instead.

See the Pen
Patterns for Practical Custom Properties: Example 3.0
by Tyler Childs (@tylerchilds)
on CodePen.

Readable theme override

As fun and cool as it is for users to control custom styles, what users pick won't always be accessible with considerations for contrast, color vision deficiency, or anyone that prefers their eyes to not bleed when reading. Remember the GeoCities days?

Let's add a class that provides a cleaner look and feel and set it on the parent element (<section>) so it overrides any student theme when it’s present.

.readable-theme [data-student-theme] {
  --student-background: hsl(50, 50%, 90%);
  --student-color: hsl(200, 50%, 10%);
  --student-font: Verdana, Geneva, sans-serif;
}
<section class="readable-theme">
  ...
</section>

We’re utilizing the cascade to override the student themes by setting a higher specificity such that the background, color, and font will be in scope and will apply to every .message ruleset.

See the Pen
Patterns for Practical Custom Properties: Example 3.1
by Tyler Childs (@tylerchilds)
on CodePen.

Pattern 4: Scoped rulesets

Speaking of scope, we can scope Custom Properties and use them to streamline what is otherwise boilerplate CSS. For example, we can define variables for different link states.

a {
  --link: hsl(230, 60%, 50%);
  --link-visited: hsl(290, 60%, 50%);
  --link-hover: hsl(230, 80%, 60%);
  --link-active: hsl(350, 60%, 50%);
}

a:link {
  color: var(--link);
}

a:visited {
  color: var(--link-visited);
}

a:hover {
  color: var(--link-hover);
}

a:active {
  color: var(--link-active);
}
<a href="#">Link Example</a>

Now that we've written out the Custom Properties globally on the <a> element and used them on our link states, we don't need to write them again. These are scoped to our <a> element’s ruleset so they are only set on anchor tags and their children. This allows us to not pollute the global namespace.

Example: Grayscale link

Going forward, we can control the links we just created by changing the Custom Properties for our different use cases. For example, let’s create a gray-colored link.

.grayscale {
  --link: LightSlateGrey;
  --link-visited: Silver;
  --link-hover: DimGray;
  --link-active: LightSteelBlue;
}
<a href="#" class="grayscale">Link Example</a>

We’ve declared a .grayscale ruleset that contains the colors for our different link states. Since the selector for this ruleset has a greater specificity then the default, these variable values are used and then applied to the pseudo-class rulesets for our link states instead of what was defined on the <a> element.

See the Pen
Patterns for Practical Custom Properties: Example 4.0
by Tyler Childs (@tylerchilds)
on CodePen.

Example: Custom links

If setting four Custom Properties feels like too much work, what if we set a single hue instead? That could make things a lot easier to manage.

.custom-link {
  --hue: 30;
  --link: hsl(var(--hue), 60%, 50%);
  --link-visited: hsl(calc(var(--hue) + 60), 60%, 50%);
  --link-hover: hsl(var(--hue), 80%, 60%);
  --link-active: hsl(calc(var(--hue) + 120), 60%, 50%);
}

.danger {
  --hue: 350;
}
<a href="#" class="custom-link">Link Example</a>
<a href="#" class="custom-link danger">Link Example</a>

See the Pen
Patterns for Practical Custom Properties: Example 4.1
by Tyler Childs (@tylerchilds)
on CodePen.

By introducing a variable for a hue value and applying it to our HSL color values in the other variables, we merely have to change that one value to update all four link states.

Calculations are powerful in combination with Custom Properties since they let
your styles be more expressive with less effort. Check out this technique by Josh Bader where he uses a similar approach to enforce accessible color contrasts on buttons.

Pattern 5: Mixins

A mixin, in regards to Custom Properties, is a function declared as a Custom Property value. The arguments for the mixin are other Custom Properties that will recalculate the mixin when they’re changed which, in turn, will update styles.

The custom link example we just looked at is actually a mixin. We can set the value for --hue and then each of the four link states will recalculate accordingly.

Example: Baseline grid foundation

Let's learn more about mixins by creating a baseline grid to help with vertical rhythm. This way, our content has a pleasant cadence by utilizing consistent spacing.

.baseline,
.baseline * {
  --rhythm: 2rem;
  --line-height: var(--sub-rhythm, var(--rhythm));
  --line-height-ratio: 1.4;
  --font-size: calc(var(--line-height) / var(--line-height-ratio));
}

.baseline {
  font-size: var(--font-size);
  line-height: var(--line-height);
}

We've applied the ruleset for our baseline grid to a .baseline class and any of its descendants.

  • --rhythm: This is the foundation of our baseline. Updating it will impact all the other properties.
  • --line-height: This is set to --rhythm by default, since --sub-rhythm is not set here.
  • --sub-rhythm: This allows us to override the --line-height — and subsequently, the --font-size — while maintaining the overall baseline grid.
  • --line-height-ratio: This helps enforce a nice amount of spacing between lines of text.
  • --font-size: This is calculated by dividing our --line-height by our --line-height-ratio.

We also set our font-size and line-height in our .baseline ruleset to use the --font-size and --line-height from our baseline grid. In short, whenever the rhythm changes, the line height and font size change accordingly while maintaining a legible experience.

OK, let’s put the baseline to use.

Let's create a tiny webpage. We'll use our --rhythm Custom Property for all of the spacing between elements.

.baseline h2,
.baseline p,
.baseline ul {
  padding: 0 var(--rhythm);
  margin: 0 0 var(--rhythm);
}

.baseline p {
  --line-height-ratio: 1.2;
}

.baseline h2 {
  --sub-rhythm: calc(3 * var(--rhythm));
  --line-height-ratio: 1;
}

.baseline p,
.baseline h2 {
  font-size: var(--font-size);
  line-height: var(--line-height);
}

.baseline ul {
  margin-left: var(--rhythm);
}
<section class="baseline">
  <h2>A Tiny Webpage</h2>
  <p>This is the tiniest webpage. It has three noteworthy features:</p>
  <ul>
    <li>Tiny</li>
    <li>Exemplary</li>
    <li>Identifies as Hufflepuff</li>
  </ul>
</section>

We're essentially using two mixins here: --line-height and --font-size. We need to set the properties font-size and line-height to their Custom Property counterparts in order to set the heading and paragraph. The mixins have been recalculated in those rulesets, but they need to be set before the updated styling will be applied to them.

See the Pen
Patterns for Practical Custom Properties: Example 5.0
by Tyler Childs (@tylerchilds)
on CodePen.

Something to keep in mind: You probably do not want to use the Custom Property values in the ruleset itself when applying mixins using a wildcard selector. It gives those styles a higher specificity than any other inheritance that comes along with the cascade, making them hard to override without using !important.

Pattern 6: Inline properties

We can also declare Custom Properties inline. Let's build a lightweight grid system demonstrate.

.grid {
  --columns: auto-fit;

  display: grid;
  gap: 10px;
  grid-template-columns: repeat(var(--columns), minmax(0, 1fr));
}
<div class="grid">
  <img src="https://www.fillmurray.com/900/600" alt="Bill Murray" />
  <img src="https://www.placecage.com/900/600" alt="Nic Cage" />
  <img src="https://www.placecage.com/g/900/600" alt="Nic Cage gray" />
  <img src="https://www.fillmurray.com/g/900/600" alt="Bill Murray gray" />
  <img src="https://www.placecage.com/c/900/600" alt="Nic Cage crazy" />
  <img src="https://www.placecage.com/gif/900/600" alt="Nic Cage gif" />
</div>

By default, the grid has equally sized columns that will automatically lay themselves into a single row.

See the Pen
Patterns for Practical Custom Properties: Example 6.0
by Tyler Childs (@tylerchilds)
on CodePen.

To control the number of columns we can set our --columns Custom Property
inline on our grid element.

<div class="grid" style="--columns: 3;">
  ...
</div>

See the Pen
Patterns for Practical Custom Properties: Example 6.1
by Tyler Childs (@tylerchilds)
on CodePen.


We just looked at six different use cases for Custom Properties — at least ones that I commonly use. Even if you were already aware of and have been using Custom Properties, hopefully seeing them used these ways gives you a better idea of when and where to use them effectively.

Are there different types of patterns you use with Custom Properties? Share them in the comments and link up some demos — I’d love to see them!

If you’re new to Custom Properties are are looking to level up, try playing around with the examples we covered here, but add media queries to the mix. You’ll see how adaptive these can be and how many interesting opportunities open up when you have the power to change values on the fly.

Plus, there are a ton of other great resources right here on CSS-Tricks to up your Custom Properties game in the Custom Properties Guide.

See the Pen
Thank you for Reading!
by Tyler Childs (@tylerchilds)
on CodePen.

The post Patterns for Practical CSS Custom Properties Use appeared first on CSS-Tricks.

Let’s Not Forget About Container Queries

Container queries are always on the top of the list of requested improvements to CSS. The general sentiment is that if we had container queries, we wouldn't write as many global media queries based on page size. That's because we're actually trying to control a more scoped container, and the only reason we use media queries for that now is because it's the best tool we have in CSS. I absolutely believe that.

There is another sentiment that goes around once in a while that goes something like: "you developers think you need container queries but you really don't." I am not a fan of that. It seems terribly obvious that we would do good things with them if they were available, not the least of which is writing cleaner, portable, understandable code. Everyone seems to agree that building UIs from components is the way to go these days which makes the need for container queries all the more obvious.

It's wonderful that there are modern JavaScript ideas that help us do use them today — but that doesn't mean the technology needs to stay there. It makes way more sense in CSS.

Here's my late 2019 thought dump on the subject:

  • Philip Walton's "Responsive Components: a Solution to the Container Queries Problem" is a great look at using JavaScript's ResizeObserver as one way to solve the issue today. It performs great and works anywhere. The demo site is the best one out there because it highlights the need for responsive components (although there are other documented use cases as well). Philip even says a pure CSS solution would be more ideal.
  • CSS nesting got a little round of enthusiasm about a year ago. The conversation makes it seem like nesting is plausible. I'm in favor of this as a long-time fan of sensible Sass nesting. It makes me wonder if the syntax for container queries could leverage the same sort of thing. Maybe nested queries are scoped to the parent selector? Or you prefix the media statement with an ampersand as the current spec does with descendant selectors?
  • Other proposed syntaxes generally involve some use of the colon, like .container:media(max-width: 400px) { }. I like that, too. Single-colon selectors (pseduo selectors) are philosophically "select the element under these conditions" — like :hover, :nth-child, etc. — so a media scope makes sense.
  • I don't think syntax is the biggest enemy of this feature; it's the performance of how it is implemented. Last I understood, it's not even performance as much as it mucks with the entire rendering flow of how browsers work. That seems like a massive hurdle. I still don't wanna forget about it. There is lots of innovation happening on the web and, just because it's not clear how to implement it today, that doesn't mean someone won't figure out a practical path forward tomorrow.

The post Let’s Not Forget About Container Queries appeared first on CSS-Tricks.