Archive

Archive for the ‘Others’ Category

Fluid Everything Else

November 5th, 2024 No comments

We all know how to do responsive design, right? We use media queries. Well no, we use container queries now, don’t we? Sometimes we get inventive with flexbox or autoflowing grids. If we’re feeling really adventurous we can reach for fluid typography.

I’m a bit uncomfortable that responsive design is often pushed into discreet chunks, like “layout A up to this size, then layout B until there’s enough space for layout C.” It’s OK, it works and fits into a workflow where screens are designed as static layouts in PhotoFigVa (caveat, I made that up). But the process feels like a compromise to me. I’ve long believed that responsive design should be almost invisible to the user. When they visit my site on a mobile device while waiting in line for K-Pop tickets, they shouldn’t notice that it’s different from just an hour ago, sitting at the huge curved gaming monitor they persuaded their boss they needed.

Consider this simple hero banner and its mobile equivalent. Sorry for the unsophisticated design. The image is AI generated, but It’s the only thing about this article that is.

The meerkat and the text are all positioned and sized differently. The traditional way to pull this off is to have two layouts, selected by a media, sorry, container query. There might be some flexibility in each layout, perhaps centering the content, and a little fluid typography on the font-size, but we’re going to choose a point at which we flip the layout in and out of the stacked version. As a result, there are likely to be widths near the breakpoint where the layout looks either a little empty or a little congested.

Is there another way?

It turns out there is. We can apply the concept of fluid typography to almost anything. This way we can have a layout that fluidly changes with the size of its parent container. Few users will ever see the transition, but they will all appreciate the results. Honestly, they will.

Let’s get this styled up

For the first step, let’s style the layouts individually, a little like we would when using width queries and a breakpoint. In fact, let’s use a container query and a breakpoint together so that we can easily see what properties need to change.

This is the markup for our hero, and it won’t change:

<div id="hero">
  <div class="details">
    <h1>LookOut</h1>
    <p>Eagle Defense System</p>
  </div>
</div>

This is the relevant CSS for the wide version:

#hero {
  container-type: inline-size;
  max-width: 1200px;
  min-width: 360px;

  .details {
    position: absolute;
    z-index: 2;

    top: 220px;
    left: 565px;

    h1 { font-size: 5rem; }

    p { font-size: 2.5rem; }
  }

  &::before {
    content: '';
    position: absolute;
    z-index: 1;

    top: 0; left: 0; right: 0; bottom: 0;

    background-image: url(../meerkat.jpg);
    background-origin: content-box;
    background-repeat: no-repeat;

    background-position-x: 0;
    background-position-y: 0;
    background-size: auto 589px;
  }
}

I’ve attached the background image to a ::before pseudo-element so I can use container queries on it (because containers cannot query themselves). We’ll keep this later on so that we can use inline container query (cqi) units. For now, here’s the container query that just shows the values we’re going to make fluid:

@container (max-width: 800px) {
  #hero {
    .details {
      top: 50px;
      left: 20px;

      h1 { font-size: 3.5rem; }

      p { font-size: 2rem; }
    }

    &::before {
      background-position-x: -310px;
      background-position-y: -25px;
      background-size: auto 710px;
    }
  }
}

You can see the code running in a live demo — it’s entirely static to show the limitations of a typical approach.

Let’s get fluid

Now we can take those start and end points for the size and position of both the text and background and make them fluid. The text size uses fluid typography in a way you are already familiar with. Here’s the result — I’ll explain the expressions once you’ve looked at the code.

First the changes to the position and size of the text:

/* Line changes
 * -12,27 +12,32
 */
  
.details {
  /* ... lines 14-16 unchanged */
  /* Evaluates to 50px for a 360px wide container, and 220px for 1200px */
  top: clamp(50px, 20.238cqi - 22.857px, 220px);

  /* Evaluates to 20px for a 360px wide container, and 565px for 1200px */
  left: clamp(20px, 64.881cqi - 213.571px, 565px);
  
  /* ... lines 20-25 unchanged */
  h1 {
    /* Evaluates to 3.5rem for a 360px wide container, and 5rem for 1200px */
    font-size: clamp(3.5rem, 2.857rem + 2.857cqi, 5rem);
    /* ... font-weight unchanged */

  }

  p {
    /* Evaluates to 2rem for a 360px wide container, and 2.5rem for 1200px */
    font-size: clamp(2rem, 1.786rem + 0.952cqi, 2.5rem);
  }
}

And here’s the background position and size for the meerkat image:

/* Line changes
 * -50,3 +55,8
 */

/* Evaluates to -310px for a 360px wide container, and 0px for 1200px */
background-position-x: clamp(-310px, 36.905cqi - 442.857px, 0px);
/* Evaluates to -25px for a 360px wide container, and 0px for 1200px */
background-position-y: clamp(-25px, 2.976cqi);
/* Evaluates to 710px for a 360px wide container, and 589px for 1200px */
background-size: auto clamp(589px, 761.857px - 14.405cqi, 710px);

Now we can drop the container query entirely.

Let’s explain those clamp() expressions. We’ll start with the expression for the top property.

/* Evaluates to 50px for a 360px wide container, and 220px for 1200px */
top: clamp(50px, 20.238cqi - 22.857px, 220px);

You’ll have noticed there’s a comment there. These expressions are a good example of how magic numbers are a bad thing. But we can’t avoid them here, as they are the result of solving some simultaneous equations — which CSS cannot do!

The upper and lower bounds passed to clamp() are clear enough, but the expression in the middle comes from these simultaneous equations:

f + 12v = 220
f + 3.6v = 50

…where f is the number of fixed-size length units (i.e., px) and v is the variable-sized unit (cqi). In the first equation, we are saying that we want the expression to evaluate to 220px when 1cqi is equal to 12px. In the second equation, we’re saying we want 50px when 1cqi is 3.6px, which solves to:

f = -22.857
v = 20.238

…and this tidies up to 20.238cqi – 22.857px in a calc()-friendly expression.

When the fixed unit is different, we must change the size of the variable units accordingly. So for the

element’s font-size we have;

/* Evaluates to 2rem for a 360px wide container, and 2.5rem for 1200px */
font-size: clamp(2rem, 1.786rem + 0.952cqi, 2.5rem);

This is solving these equations because, at a container width of 1200px, 1cqi is the same as 0.75rem (my rems are relative to the default UA stylesheet, 16px), and at 360px wide, 1cqi is 0.225rem.

f + 0.75v = 2.5
f + 0.225v = 2

This is important to note: The equations are different depending on what unit you are targeting.

Honestly, this is boring math to do every time, so I made a calculator you can use. Not only does it solve the equations for you (to three decimal places to keep your CSS clean) it also provides that helpful comment to use alongside the expression so that you can see where they came from and avoid magic numbers. Feel free to use it. Yes, there are many similar calculators out there, but they concentrate on typography, and so (rightly) fixate on rem units. You could probably port the JavaScript if you’re using a CSS preprocessor.

The clamp() function isn’t strictly necessary at this point. In each case, the bounds of clamp() are set to the values of when the container is either 360px or 1200px wide. Since the container itself is constrained to those limits — by setting min-width and max-width values — the clamp() expression should never invoke either bound. However, I prefer to keep clamp() there in case we ever change our minds (which we are about to do) because implicit bounds like these are difficult to spot and maintain.

Avoiding injury

We could consider our work finished, but we aren’t. The layout still doesn’t quite work. The text passes right over the top of the meerkat’s head. While I have been assured this causes the meerkat no harm, I don’t like the look of it. So, let’s make some changes to make the text avoid hitting the meerkat.

The first is simple. We’ll move the meerkat to the left more quickly so that it gets out of the way. This is done most easily by changing the lower end of the interpolation to a wider container. We’ll set it so that the meerkat is fully left by 450px rather than down to 360px. There’s no reason the start and end points for all of our fluid expressions need to align with the same widths, so we can keep the other expressions fluid down to 360px.

Using my trusty calculator, all we need to do is change the clamp() expressions for the background-position properties:

/* Line changes
 * -55,5 +55,5
 */

/* Evaluates to -310px for a 450px wide container, and 0px for 1200px */
background-position-x: clamp(-310px, 41.333cqi - 496px, 0px);

/* Evaluates to -25px for a 450px wide container, and 0px for 1200px */
background-position-y: clamp(-25px, 3.333cqi - 40px, 0px);

This improves things, but not totally. I don’t want to move it any quicker, so next we’ll look at the path the text takes. At the moment it moves in a straight line, like this:

Showing the path the heading travels as the hero banner goes from a desktop size to a tablet size to a mobile size.

But can we bend it? Yes, we can.

A Bend in the path

One way we can do this is by defining two different interpolations for the top coordinate that places the line at different angles and then choosing the smallest one. This way, it allows the steeper line to “win” at larger container widths, and the shallower line becomes the value that wins when the container is narrower than about 780px. The result is a line with a bend that misses the meerkat.

All we’re changing is the top value, but we must calculate two intermediate values first:

/* Line changes
 * -18,2 +18,9 @@
 */

/* Evaluates to 220px for a 1200px wide container, and -50px for 360px */
--top-a: calc(32.143cqi - 165.714px);

/* Evaluates to 120px for a 1200px wide container, and 50px for 360px */
--top-b: calc(20px + 8.333cqi);

/* By taking the max, --topA is used at lower widths, with --topB taking over when wider.
We only need to apply clamp when the value is actually used */
top: clamp(50px, max(var(--top-a), var(--top-b)), 220px);

For these values, rather than calculating them formally using a carefully chosen midpoint, I experimented with the endpoints until I got the result I wanted. Experimentation is just as valid as calculation as a way of getting the result you need. In this case, I started with duplicates of the interpolation in custom variables. I could have split the path into explicit sections using a container query, but that doesn’t reduce the math overhead, and using the min() function is cleaner to my eye. Besides, this article isn’t strictly about container queries, is it?

Now the text moves along this path. Open up the live demo to see it in action.

Showing the path the heading travels as the hero banner goes from a desktop size to a tablet size to a mobile size. The path makes a sharp angle as it travels over the meerkat.

CSS can’t do everything

As a final note on the calculations, it’s worth pointing out that there are restrictions as far as what we can and can’t do. The first, which we have already mitigated a little, is that these interpolations are linear. This means that easing in or out, or other complex behavior, is not possible.

Another major restriction is that CSS can only generate length values this way, so there is no way in pure CSS to apply, for example, opacity or a rotation angle that is fluid based on the container or viewport size. Preprocessors can’t help us here either because the limitation is on the way calc() works in the browser.

Both of these restrictions can be lifted if you’re prepared to rely on a little JavaScript. A few lines to observe the width of the container and set a CSS custom property that is unitless is all that’s needed. I’m going to use that to make the text follow a quadratic Bezier curve, like this:

Showing the path the heading travels as the hero banner goes from a desktop size to a tablet size to a mobile size. The path makes a smooth curve as it travels over the meerkat.

There’s too much code to list here, and too much math to explain the Bezier curve, but go take a look at it in action in this live demo.

We wouldn’t even need JavaScript if expressions like calc(1vw / 1px) didn’t fail in CSS. There is no reason for them to fail since they represent a ratio between two lengths. Just as there are 2.54cm in 1in, there are 8px in 1vw when the viewport is 800px wide, so calc(1vw / 1px) should evaluate to a unitless 8 value.

They do fail though, so all we can do is state our case and move on.

Fluid everything doesn’t solve all layouts

There will always be some layouts that need size queries, of course; some designs will simply need to snap changes at fixed breakpoints. There is no reason to avoid that if it’s right. There is also no reason to avoid mixing the two, for example, by fluidly sizing and positioning the background while using a query to snap between grid definitions for the text placement. My meerkat example is deliberately contrived to be simple for the sake of demonstration.

One thing I’ll add is that I’m rather excited by the possibility of using the new Anchor Positioning API for fluid positioning. There’s the possibility of using anchor positioning to define how two elements might flow around the screen together, but that’s for another time.


Fluid Everything Else originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

Categories: Designing, Others Tags:

Why Optimizing Your Lighthouse Score Is Not Enough For A Fast Website

November 5th, 2024 No comments

This article is a sponsored by DebugBear

We’ve all had that moment. You’re optimizing the performance of some website, scrutinizing every millisecond it takes for the current page to load. You’ve fired up Google Lighthouse from Chrome’s DevTools because everyone and their uncle uses it to evaluate performance.

After running your 151st report and completing all of the recommended improvements, you experience nirvana: a perfect 100% performance score!

Time to pat yourself on the back for a job well done. Maybe you can use this to get that pay raise you’ve been wanting! Except, don’t — at least not using Google Lighthouse as your sole proof. I know a perfect score produces all kinds of good feelings. That’s what we’re aiming for, after all!

Google Lighthouse is merely one tool in a complete performance toolkit. What it’s not is a complete picture of how your website performs in the real world. Sure, we can glean plenty of insights about a site’s performance and even spot issues that ought to be addressed to speed things up. But again, it’s an incomplete picture.

What Google Lighthouse Is Great At

I hear other developers boasting about perfect Lighthouse scores and see the screenshots published all over socials. Hey, I just did that myself in the introduction of this article!

Lighthouse might be the most widely used web performance reporting tool. I’d wager its ubiquity is due to convenience more than the quality of its reports.

Open DevTools, click the Lighthouse tab, and generate the report! There are even many ways we can configure Lighthouse to measure performance in simulated situations, such as slow internet connection speeds or creating separate reports for mobile and desktop. It’s a very powerful tool for something that comes baked into a free browser. It’s also baked right into Google’s PageSpeed Insights tool!

And it’s fast. Run a report in Lighthouse, and you’ll get something back in about 10-15 seconds. Try running reports with other tools, and you’ll find yourself refilling your coffee, hitting the bathroom, and maybe checking your email (in varying order) while waiting for the results. There’s a good reason for that, but all I want to call out is that Google Lighthouse is lightning fast as far as performance reporting goes.

To recap: Lighthouse is great at many things!

  • It’s convenient to access,
  • It provides a good deal of configuration for different levels of troubleshooting,
  • And it spits out reports in record time.

And what about that bright and lovely animated green score — who doesn’t love that?!

OK, that’s the rosy side of Lighthouse reports. It’s only fair to highlight its limitations as well. This isn’t to dissuade you or anyone else from using Lighthouse, but more of a heads-up that your score may not perfectly reflect reality — or even match the scores you’d get in other tools, including Google’s own PageSpeed Insights.

It Doesn’t Match “Real” Users

Not all data is created equal in capital Web Performance. It’s important to know this because data represents assumptions that reporting tools make when evaluating performance metrics.

The data Lighthouse relies on for its reporting is called simulated data. You might already have a solid guess at what that means: it’s synthetic data. Now, before kicking simulated data in the knees for not being “real” data, know that it’s the reason Lighthouse is super fast.

You know how there’s a setting to “throttle” the internet connection speed? That simulates different conditions that either slow down or speed up the connection speed, something that you configure directly in Lighthouse. By default, Lighthouse collects data on a fast connection, but we can configure it to something slower to gain insights on slow page loads. But beware! Lighthouse then estimates how quickly the page would have loaded on a different connection.

DebugBear founder Matt Zeunert outlines how data runs in a simulated throttling environment, explaining how Lighthouse uses “optimistic” and “pessimistic” averages for making conclusions:

“[Simulated throttling] reduces variability between tests. But if there’s a single slow render-blocking request that shares an origin with several fast responses, then Lighthouse will underestimate page load time.

Lighthouse averages optimistic and pessimistic estimates when it’s unsure exactly which nodes block rendering. In practice, metrics may be closer to either one of these, depending on which dependency graph is more correct.”

And again, the environment is a configuration, not reality. It’s unlikely that your throttled conditions match the connection speeds of an average real user on the website, as they may have a faster network connection or run on a slower CPU. What Lighthouse provides is more like “on-demand” testing that’s immediately available.

That makes simulated data great for running tests quickly and under certain artificially sweetened conditions. However, it sacrifices accuracy by making assumptions about the connection speeds of site visitors and averages things in a way that divorces it from reality.

While simulated throttling is the default in Lighthouse, it also supports more realistic throttling methods. Running those tests will take more time but give you more accurate data. The easiest way to run Lighthouse with more realistic settings is using an online tool like the DebugBear website speed test or WebPageTest.

It Doesn’t Impact Core Web Vitals Scores

These Core Web Vitals everyone talks about are Google’s standard metrics for measuring performance. They go beyond simple “Your page loaded in X seconds” reports by looking at a slew of more pertinent details that are diagnostic of how the page loads, resources that might be blocking other resources, slow user interactions, and how much the page shifts around from loading resources and content. Zeunert has another great post here on Smashing Magazine that discusses each metric in detail.

The main point here is that the simulated data Lighthouse produces may (and often does) differ from performance metrics from other tools. I spent a good deal explaining this in another article. The gist of it is that Lighthouse scores do not impact Core Web Vitals data. The reason for that is Core Web Vitals relies on data about real users pulled from the monthly-updated Chrome User Experience (CrUX) report. While CrUX data may be limited by how recently the data was pulled, it is a more accurate reflection of user behaviors and browsing conditions than the simulated data in Lighthouse.

The ultimate point I’m getting at is that Lighthouse is simply ineffective at measuring Core Web Vitals performance metrics. Here’s how I explain it in my bespoke article:

“[Synthetic] data is fundamentally limited by the fact that it only looks at a single experience in a pre-defined environment. This environment often doesn’t even match the average real user on the website, who may have a faster network connection or a slower CPU.”

I emphasized the important part. In real life, users are likely to have more than one experience on a particular page. It’s not as though you navigate to a site, let it load, sit there, and then close the page; you’re more likely to do something on that page. And for a Core Web Vital metric that looks for slow paint in response to user input — namely, Interaction to Next Paint (INP) — there’s no way for Lighthouse to measure that at all!

It’s the same deal for a metric like Cumulative Layout Shift (CLS) that measures the “visible stability” of a page layout because layout shifts often happen lower on the page after a user has scrolled down. If Lighthouse relied on CrUX data (which it doesn’t), then it would be able to make assumptions based on real users who interact with the page and can experience CLS. Instead, Lighthouse waits patiently for the full page load and never interacts with parts of the page, thus having no way of knowing anything about CLS.

But It’s Still a “Good Start”

That’s what I want you to walk away with at the end of the day. A Lighthouse report is incredibly good at producing reports quickly, thanks to the simulated data it uses. In that sense, I’d say that Lighthouse is a handy “gut check” and maybe even a first step to identifying opportunities to optimize performance.

But a complete picture, it’s not. For that, what we’d want is a tool that leans on real user data. Tools that integrate CrUX data are pretty good there. But again, that data is pulled every month (28 days to be exact) so it may not reflect the most recent user behaviors and interactions, although it is updated daily on a rolling basis and it is indeed possible to query historical records for larger sample sizes.

Even better is using a tool that monitors users in real-time.

Data pulled directly from the site of origin is truly the gold standard data we want because it comes from the source of truth. That makes tools that integrate with your site the best way to gain insights and diagnose issues because they tell you exactly how your visitors are experiencing your site.

I’ve written about using the Performance API in JavaScript to evaluate custom and Core Web Vitals metrics, so it’s possible to roll that on your own. But there are plenty of existing services out there that do this for you, complete with visualizations, historical records, and true real-time user monitoring (often abbreviated as RUM). What services? Well, DebugBear is a great place to start. I cited Matt Zeunert earlier, and DebugBear is his product.

So, if what you want is a complete picture of your site’s performance, go ahead and start with Lighthouse. But don’t stop there because you’re only seeing part of the picture. You’ll want to augment your findings and diagnose performance with real-user monitoring for the most complete, accurate picture.

Categories: Others Tags:

Why Every Entrepreneur Should Start a Blog

November 4th, 2024 No comments

As an entrepreneur, you have to be willing to self-promote and build your own personal brand (alongside that of your business brands, of course). And while there are hundreds of ways to do this, blogging is still one of the best.

The Perks of Building Your Own Blog

As an entrepreneur, you have lots of different avenues available to you for building your brand and establishing connections. However, blogging remains one of the best options. Here a few of the top reasons why:

1. Strengthens Your Online Presence

Having a strong online presence is important. And blogging is one of the best ways to increase your visibility and ensure that potential clients, partners, and investors can easily find you. Your blog will allow you to create multiple entry points for people to discover your personal brand and business.

A blog acts as a hub for all your thoughts, ideas, and expertise. It gives people a central place to learn about you and your business, beyond what’s on your social media profiles or website landing pages. Each blog post you publish is another opportunity to attract visitors to your site, showcase your knowledge, and demonstrate your value.

Plus, a blog allows you to maintain control over your narrative. Unlike social media, where algorithms can change and limit your reach, your blog is your space. You decide the content, the message, and how you engage with your audience.

2. Establishes Authority

Regularly blogging about topics related to your industry is one of the best ways to establish yourself as an expert in your field. 

When you share your knowledge through well-researched, insightful blog posts, you’re not just helping your readers – you’re building credibility. Over time, your audience will start to see you as a go-to resource for industry-related information. This authority can translate into more business opportunities, as people are more likely to trust and engage with someone who demonstrates expertise.

Being seen as an authority in your field also opens doors to speaking engagements, guest appearances on other platforms, and collaborations with other experts in your industry. It can even help you gain media attention, as journalists often look for authoritative sources to quote in articles.

3. Drives Organic Search Traffic

One of the biggest benefits of blogging for entrepreneurs is the opportunity to attract organic search traffic. Every blog post you write is an opportunity to optimize for search engines, helping you rank higher on Google and other search platforms. This is especially important if you’re just starting out and don’t have a huge marketing budget.

By focusing on SEO-rich content  – content that’s optimized with relevant keywords, meta descriptions, and internal/external links – you can naturally bring in readers who are searching for information related to your business or industry. For example, if you’re a fitness entrepreneur, a blog post about “how to stay fit while working from home” could attract people searching for fitness tips, who might then learn more about your products or services.

As you publish more content and your blog starts gaining traction in search results, you’ll notice an increase in organic traffic, which means more eyes on your brand and business without spending extra money on ads.

4. Builds and Fosters a Community

Blogging gives you a unique opportunity to directly engage with your audience and foster a sense of community around your brand. When you write blog posts that resonate with your readers, they’re more likely to interact with your content – whether by leaving comments, sharing your posts on social media, or subscribing to your newsletter.

This type of engagement allows you to build a loyal following of people who not only support your business but also feel connected to you personally. The more you interact with your readers, the stronger that connection becomes. Blogging also opens up the opportunity for valuable feedback. Your readers might leave comments that inspire new blog topics, help you improve your products or services, or give you insights into what your audience is most interested in.

5. Natural Promotion for Your Products

One of the most effective ways to promote your products and services without being too salesy is through blogging. Rather than directly pitching your offerings, you can write informative, helpful content that naturally ties back to what you sell.

For example, if you run an online store that sells eco-friendly products, you could write blog posts about the importance of sustainability, offer tips for reducing waste, and highlight the benefits of using green products. Throughout the post, you can subtly mention your products and link to them as part of the solution.

This approach positions you as someone who cares about educating your audience, rather than just pushing a sale. And when readers see the value in what you offer, they’re more likely to trust your recommendations and make a purchase.

6. Keeps You Relevant and Adaptable

Blogging keeps you relevant in your industry. It gives you a platform to share your thoughts on the latest trends, discuss emerging technologies, and offer insights on current events that affect your niche. By staying active in the conversation, you show that you’re not only knowledgeable but also adaptable.

As your industry evolves, your blog can evolve, too. It’s a flexible tool that can grow with your business and help you stay ahead of the curve. Whether you’re launching a new product, expanding into a new market, or simply shifting focus, your blog can reflect those changes and keep your audience informed.

Putting it All Together

There’s no one-size-fits-all solution to building your brand as an entrepreneur. However, certain strategies pack more punch than others. Blogging is one of them. By starting a blog, you can enjoy many of the benefits highlighted in this article and give yourself a better chance to be successful in the months and years to come!

Featured Image by Andrew Neel on Unsplash

The post Why Every Entrepreneur Should Start a Blog appeared first on noupe.

Categories: Others Tags:

8 Things to Do Before Transitioning Your Small Business From a Side Hustle to Full-Time

November 4th, 2024 No comments

If you have a profitable side hustle, you’ve probably considered taking your business full-time. However, before you take the leap and transition to life as a full-time entrepreneur, there are a few things you should do.

Some tasks are simple, like opening a business bank account and setting concrete goals. Others, like building a professional website, investing in growth strategies, and networking, will take more time and consideration.

There’s no doubt the process can be overwhelming, so here are eight specific things you can do to prepare for the transition.

Register Your Business and Open a Bank Account

If you haven’t yet, make sure to register your business. An accountant or business attorney can advise you on the best business formation, such as an LLC. Once you’ve registered your business officially, open a dedicated business bank account.

Many solopreneurs start their businesses without these initial steps. However, if you want to transition to full-time self-employment, it’s essential to treat your business like the professional entity that it is.

Set Concrete Goals

Successful entrepreneurs create clearly defined, easy-to-track business goals. So, before you quit your job and take your business full-time, write down specific benchmarks you want to achieve. Whether it’s a certain number of customers or a revenue goal, sketch out where you’d like to be at the three-month, six-month, and twelve-month mark of being a full-time entrepreneur.

Create a business plan that outlines how you will market your business, how you plan to grow it, and why you expect to stand out in the market. Researching your competitors and seeing what they’re doing right (and wrong) is also important.

Take this information and use your research to help you make a comprehensive plan to follow. That way, you know what to do on your first day of self-employment and beyond.

Secure Funding

Some businesses, particularly online ones, don’t have significant start-up costs. However, others, such as brick-and-mortar businesses or technology start-ups, will require upfront cash. 

There are many different ways you can fund your business start-up costs. You can self-fund it from personal savings, get a personal loan, or apply for a business line of credit

The funding route you choose will depend on your business goals, the type of business you have, and whether or not you want to give up equity in exchange for funding. For example, many entrepreneurs choose to pitch venture capital firms but give up equity in the process. Others apply for SBA loans, like the SBA 504 loan.

Create a Website and Social Media Presence

Your website and social media profiles are some of the first things your customers or clients will see. Make sure you have a professional website and that your social media accounts reflect your business values. 

Your business website should explain what you do clearly and have an easy way to contact you, while your social accounts should have a consistent brand presence with similar color schemes and your logo. 

Update your social media accounts regularly and take the time to learn about social media and email marketing as ways to grow your client and customer base.

Build a Strong Client or Customer List

Speaking of clients and customers, it’s vital to have plans to reach them before you make the leap to self-employment. If you have clients that use your services, build a list of several that can provide recurring revenue so you can project your first few months of self-employment income.

If you serve customers, take the time to understand the best ways to acquire new ones. Test multiple marketing strategies and methods until you find a consistent way to keep customers coming back to your business regularly. 

Once you build a strong and consistent client or customer base and you know you can reliably earn income while you’re self-employed, you can begin to make concrete plans to transition into full-time entrepreneurship. 

Set Up Health Insurance and Benefits

While some may enjoy the benefits of insurance coverage from a spouse, many others will need to find their own plan after leaving their day job. For those who’ve never done this before, this can require a bit of research. 

When you work for yourself, you’ll also need to arrange any “benefits,” like retirement plans. It’s a good idea to explore these costs ahead of time to ensure that your business income can cover the cost of your taxes, payroll, and more.

Invest in Growth Strategies

As you’re preparing to take your business full-time, invest in growth strategies. For example, make sure you’re regularly learning new skills and researching business grants. If you know you’ll need to purchase real estate as part of your business plan, find ways that you can buy property affordably or qualify for home buyer rebates.

Learn how to manage your bookkeeping and spend time understanding your cash flow. This information will help you know whether or not you can hire additional team members or invest in other products or services in the future as you grow.

Network and Find Mentors

Mentors who have made the leap from side hustle to full-time job can help you determine whether or not you’re ready to do the same. When you network and learn from others, it can help you avoid mistakes, saving you valuable time and money.

Networking in person is ideal, but it’s also wise to build your connections on LinkedIn to connect with entrepreneurs in similar industries. Connecting online means you’re not limited to business owners in your area, dramatically expanding your reach.

Take the Leap

Once you’ve completed the steps above, you’re likely ready to take the leap, even if you don’t feel completely ready. Many people are worried about their livelihoods, rising costs, and the economy overall, but data from a 2024 economic outlook shows economists don’t believe a recession is imminent. That means it might be a perfect time to break out on your own.

Keep these steps in mind before going full-time, and you’ll put yourself on the path to business success.

Featured Image by Microsoft Edge on Unsplash

The post 8 Things to Do Before Transitioning Your Small Business From a Side Hustle to Full-Time appeared first on noupe.

Categories: Others Tags:

What Is Psychographic Segmentation and How Can It Boost Engagement?

November 1st, 2024 No comments

Any kind of marketing approach that gives you a deeper insight into your customers has the potential to help you make stronger connections with them.

Psychographic segmentation is a perfect example. Unlike demographic or behavioral segmentation, it goes into depth about what makes your customers tick, which means you can better understand how to reach out to them in a way that resonates.

In this article, we’ll look at what psychographic segmentation is, how it works, and how to implement it in your marketing campaigns.

What is Psychographic Segmentation?

Using psychographic segmentation is a way of developing a deeper understanding of your target audiences. Unlike demographic segmentation, which focuses on easily pinned-down facts like age, income level, or location, it involves categorizing your customer base by studying their psychological characteristics.

Delineating customer segments via psychological traits means you can build up a picture of what motivates each group to commit to certain buying decisions. In turn, this can help you develop more effective marketing strategies and increase your conversion rates.

Why Psychographic Segmentation is Important for Engagement

Consumer behavior isn’t monolithic. In other words, not all of your target customers arrive at a purchase decision via the same route. But the one thing they all have in common is that they’re more likely to respond if you tailor your messaging to their personal preferences.

When you develop a deep understanding of the psychological factors underpinning their motivation, you can create appropriate content for different target segments. For instance, rather than simply sending a generic check-in email, you can curate messages that resonate more deeply with your target audience, boosting engagement.

rendered image of a brain bathed in blue light

Other Benefits of Using Psychographic Segmentation

As well as boosted engagement, there are a number of other advantages to deploying psychographic segmentation in your marketing. These include:

More effective product development: Building up a full picture of your potential customers’ psychographic characteristics can provide an excellent starting point for developing new products that meet your target audience’s needs.

Improved customer service: The better you understand your customer base, the easier it is to deliver top-tier customer service. This makes it more straightforward to implement first-call resolution best practices in a contact center, for instance, because your agents will be able to use more personalized insights with each customer to help give them what they need.

More accurate targeting: Splitting your target market into psychographic segments enables you to connect with different groups of customers in a much more effective way.

Bear in mind that two customers may have an identical demographic profile but have very different interests and motivations.

For instance, imagine two women in the 25-34 age group who live in the same city, and each have two children under 10 years of age. But one is an avid hiker, while the other prefers to stay home and try out new recipes. Ideally, you’d be tweaking the messaging your brand sends out to each one accordingly to try to encourage deeper engagement from both customers.

With that in mind, let’s consider the most important psychographic segmentation variables to look at.

Psychographic Segmentation Factors

So, what are the main psychographic factors you should be focusing on? There are no hard and fast rules about this, but there are several areas that companies often zero in on to try to create more effective marketing campaigns. These are:

Consumer Personality Traits

You don’t need to go full Myers-Briggs here. It’s not realistic to ask every prospective customer to fill out a detailed personality test, but having a grasp of some of their more obvious personality traits can help you gain valuable insights.

For instance, are they more extroverted or introverted? Who are the more adventurous and open-minded individuals, and who are more reserved? There are ways you can phrase open-ended questions to try to encourage survey respondents to reveal these traits in a non-intrusive way, such as:

  • What motivates you to achieve your goals?
  • Do you prefer to base decisions on facts or intuition?
  • How do you respond to everyday challenges?

You can then build up quite a rich picture of each customer personality, which will give an indication of the types of products they might be interested in and what their general consumer preferences are likely to be.

Core Values

Understanding what’s important to your customers is vital for fine-tuning your brand storytelling. Of course, most brands will want to avoid more potentially divisive areas like direct political statements (unless the brand itself has a specific connection that makes these relevant).

However you can dig into your potential customers’ beliefs in ways that your brand can relate to. For example:

  • Which of your customers prioritize family?
  • Who is passionate about environmental issues?
  • How important are social responsibility initiatives to your customers?

Interests and Hobbies

This one is fairly easy to pick up on because people love talking about their interests. Which customers lead an active lifestyle and participate in outdoor activities? Who are the passionate music fans or sports lovers? Who enjoys creating and crafts?

Researching this aspect of your customers’ daily activities is obviously going to be highly relevant if you sell products that cater to those interests. But even if you don’t, it can be very useful to seek out this information because it helps you create more accurate buyer personas and target customer profiles.

Lifestyle Preferences

On a day-to-day basis, what do your customers get up to? Are they busy professionals who grab a quick coffee each morning on the go? Do they spend their weekends traveling to follow their favorite teams? Are they health-conscious people who go to the gym regularly?

Understanding your customers’ lifestyle preferences gives you insight into their purchasing habits at a deeper level. It’s also an excellent way of identifying which channels to reach out on to best connect with your potential clients.

Common Research Methods for Psychographic Segmentation

So, how do you go about collecting this kind of information? There are a number of routes you can take, and it’s usually best to use a mixture of different approaches. Try to incorporate a few of these:

Online surveys: Sending out psychographic surveys is one of the quickest ways of understanding your customers. It’s also one of the best ways to get broad-based data, since it doesn’t take much time commitment on the part of the customer. Consider sending surveys out to your email list or putting short pop-up surveys on your website. Offering an incentive, such as a discount voucher, can increase response rates.

Social listening: The advantage of social listening is that you can essentially eavesdrop on customers’ candid opinions. Whether they have a problem with your product or service or are particularly loyal customers who love your brand, you’ll find honest criticism on social media. Moreover, social platform analytics are useful for getting insights into your followers’ interests and purchasing habits.

Focus groups: For a more detailed examination of your customers’ opinions and thoughts, you can use focus groups or one-to-one interviews. These can be carried out online or in person, but they require a relatively heavy time investment from the participants. So, again, offer an attractive incentive to encourage people to participate.

Analytics tools: You can collect some psychographic data, like the interests your website visitors have, from standard tools like Google Analytics. In addition, you can glean more in-depth information by tracking online behavior using heatmaps and session recordings.

Existing research: Another option is to explore existing research that’s already in the public domain. Of course, this won’t give you detailed information about your individual customers. Nevertheless, if you have a reasonable grasp of who your customer base is, you can often find reports from sources such as government websites or industry experts that provide consumer insights you’ll be able to use, at least as a starting point.

How to Implement Psychographic Segmentation

Collecting the information is one thing; making it work for your marketing campaigns is quite another. But if you can get it right, it can help support a full-funnel marketing approach that delivers excellent results. Here are the steps you’ll need to follow:

1. Collect the psychographic data using your chosen research methods.

2. Analyze the data and use it to place your customers into individual categories of people who share certain key characteristics in common.

3. Devise detailed buyer personas based on these categories.

4. Use these to help create personalized brand messaging and content tailored for each category.

5. Keep collecting data regularly and reviewing your strategy. It will need to be constantly updated to maintain relevance.

Final Thoughts

There are several approaches to customer segmentation you can take, and the ones you choose will depend on your brand goals.

The key thing to remember about psychographic segmentation is that it deals with the “why” questions: why do your customers live their lives the way they do? Why do they make certain product choices over others? Why do they respond to some messages more strongly?

Tapping into those underlying motivations is an excellent way of driving higher engagement because you’ll be able to connect with potential customers on a more fundamental level. And that’s a terrific way of making sure those customers come back time and time again.

Featured image by Adam Wilson on Unsplash

The post What Is Psychographic Segmentation and How Can It Boost Engagement? appeared first on noupe.

Categories: Others Tags:

State of CSS 2024 Results

October 30th, 2024 No comments

They’re out! Like many of you, I look forward to these coming out each year. I don’t put much stock in surveys but they can be insightful and give a snapshot of the CSS zeitgeist. There are a few little nuggets in this year’s results that I find interesting. But before I get there, you’ll want to also check out what others have already written about it.

Oh, I guess that’s it — at least it’s the most formal write-up I’ve seen. There’s a little summary by Ahmad Shadeed at the end of the survey that generally rounds things up. I’ll drop in more links as I find ’em.

In no particular order…

Demographics

Josh has way more poignant thoughts on this than I do. He rightfully calls out discrepancies in gender pay and regional pay, where men are way more compensated than women (a nonsensical and frustratingly never-ending trend) and the United States boasts more $100,000 salaries than anywhere else. The countries with the highest salaries were also the most represented in survey responses, so perhaps the results are no surprise. We’re essentially looking at a snapshot of what it’s like to be a rich, white male developer in the West.

Besides pay, my eye caught the Age Group demographics. As an aging front-ender, I often wonder what we all do when we finally get to retirement age. I officially dropped from the most represented age group (30-39, 42%) a few years ago into the third most represented tier (40-49, 21%). Long gone are my days being with the cool kids (20-29, 27%).

And if the distribution is true to life, I’m riding fast into my sunset years and will be only slightly more represented than those getting into the profession. I don’t know if anyone else feels similarly anxious about aging in this industry — but if you’re one of the 484 folks who identify with the 50+ age group, I’d love to talk with you.

Before we plow ahead, I think it’s worth calling out how relatively “new” most people are to front-end development.

Bar chart with years of experience from the state of CSS 2024 survey.

Wow! Forty-freaking-four percent of respondents have less than 10 years of experience. Yes, 10 years is a high threshold, but we’re still talking about a profession that popped up in recent memory.

For perspective, someone developing for 10 years came to the field around 2014. That’s just when we were getting Flexbox, and several years after the big bang of CSS 3 and HTML 5. That’s just under half of developers who never had to deal with the headaches of table layouts, clearfix hacks, image sprites, spacer images, and rasterized rounded corners. Ethan Marcotte’s seminal article on “Responsive Web Design” predates these folks by a whopping four years!

That’s just wild. And exciting. I’m a firm believer in the next generation of front-enders but always hope that they learn from our past mistakes and become masters at the basics.

Features

I’m not entirely sure what to make of this section. When there are so many CSS features, how do you determine which are most widely used? How do you pare it down to just 50 features? Like, are filter effects really the most widely used CSS feature? So many questions, but the results are always interesting nonetheless.

What I find most interesting are the underused features. For example, hanging-punctuation comes in dead last in usage (1.57%) but is the feature that most developers (52%) have on their reading list. (If you need some reading material on it, Chris initially published the Almanac entry for hanging-punctuation back in 2013.)

I also see Anchor Positioning at the end of the long tail with reported usage at 4.8%. That’ll go up for sure now that we have at least one supporting browser engine (Chromium) but also given all of the tutorials that have sprung up in the past few months. Yes, we’ve contributed to that noise… but it’s good noise! I think Juan published what might be the most thorough and thoughtful guide on the topic yet.

I’m excited to see Cascade Layers falling smack dab in the middle of the pack at a fairly robust 18.7%. Cascade Layers are super approachable and elegantly designed that I have trouble believing anybody these days when they say that the CSS Cascade is difficult to manage. And even though @scope is currently low on the list (4.8%, same as Anchor Positioning), I’d bet the crumpled gum wrapper in my pocket that the overall sentiment of working with the Cascade will improve dramatically. We’ll still see “CSS is Awesome” memes galore, but they’ll be more like old familiar dad jokes in good time.

(Aside: Did you see the proposed designs for a new CSS logo? You can vote on them as of yesterday, but earlier versions played off the “CSS is Awesome” mean quite beautifully.)

Interestingly enough, viewport units come in at Number 11 with 44.2% usage… which lands them at Number 2 for most experience that developers have with CSS layout. Does that suggest that layout features are less widely used than CSS filters? Again, so many questions.

Frameworks

How many of you were surprised that Tailwind blew past Bootstrap as Top Dog framework in CSS Land? Nobody, right?

More interesting to me is that “No CSS framework” clocks in at Number 13 out of 21 list frameworks. Sure, its 46 votes are dwarfed by the 138 for Material UI at Number 10… but the fact that we’re seeing “no framework” as a ranking option at all would have been unimaginable just three years ago.

The same goes for CSS pre/post-processing. Sass (67%) and PostCSS (38%) are the power players, but “None” comes in third at 19%, ahead of Less, Stylus, and Lightning CSS.

It’s a real testament to the great work the CSSWG is doing to make CSS better every day. We don’t thank the CSSWG enough — thank you, team! Y’all are heroes around these parts.

CSS Usage

Josh already has a good take on the fact that only 67% of folks say they test their work on mobile phones. It should be at least tied with the 99% who test on desktops, right? Right?! Who knows, maybe some responses consider things like “Responsive Design Mode” desktop features to be the equivalent of testing on real mobile devices. I find it hard to believe that only 67% of us test mobile.

Oh, and The Great Divide is still alive and well if the results are true and 53% write more JavsScript than CSS in their day-to-day.

Missing CSS Features

This is always a fun topic to ponder. Some of the most-wanted CSS features have been lurking around 10+ years. But let’s look at the top three form this year’s survey:

  • Mixins
  • Conditional Logic
  • Masonry

We’re in luck team! There’s movement on all three of those fronts:

Resources

This is where I get to toot our own horn a bit because CSS-Tricks continues to place first among y’all when it comes to the blogs you follow for CSS happenings.

I’m also stoked to see Smashing Magazine right there as well. It was fifth in 2023 and I’d like to think that rise is due to me joining the team last year. Correlation implies causation, amirite?

But look at Kevin Powell and Josh in the Top 10. That’s just awesome. It speaks volumes about their teaching talents and the hard work they put into “helping people fall in love with CSS” as Kevin might say it. I was able to help Kevin with a couple of his videos last year (here’s one) and can tell you the guy cares a heckuva lot about making CSS approachable and fun.

Honestly, the rankings are not what we live for. Now that I’ve been given a second wind to work on CSS-Tricks, all I want is to publish things that are valuable to your everyday work as front-enders. That’s traditionally happened as a stream of daily articles but is shifting to more tutorials and resources, whether it’s guides (we’ve published four new ones this year), taking notes on interesting developments, spotlighting good work with links, or expanding the ol’ Almanac to account for things like functions, at-rules, and pseudos (we have lots of work to do).

My 2024 Pick

No one asked my opinion but I’ll say it anyway: Personal blogging. I’m seeing more of us in the front-end community getting back behind the keyboards of their personal websites and I’ve never been subscribed to more RSS feeds than I am today. Some started blogging as a “worry stone” during the 2020 lockdown. Some abandoned socials when Twitter X imploded. Some got way into the IndieWeb. Webrings and guestbooks are even gaining new life. Sure, it can be tough keeping up, but what a good problem to have! Let’s make RSS king once and for all.

That’s a wrap!

Seriously, a huge thanks to Sacha Greif and the entire Devographics team for the commitment to putting this survey together every year. It’s always fun. And the visualizations are always to die for.


State of CSS 2024 Results originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

Categories: Designing, Others Tags:

Tooltip Best Practices

October 29th, 2024 No comments
Two examples of a bell icon with content displayed beneath them, one as a primary label and one as an auxiliary description.

Labeling

If your tooltip is used to label an icon — using only one or two words — you should use the aria-labelledby attribute to properly label it since it is attached to nothing else on the page that would help identify it.

<button aria-labelledby="notifications"> ... </button>
<div role="tooltip" id="notifications">Notifications</div> 

You could provide contextual information, like stating the number of notifications, by giving a space-separated list of ids to aria-labelledby.

Bell icon with a badge indicating three notifications and a tooltip displayed to the right.
<button aria-labelledby="notifications-count notifications-label">  
  <!-- bell icon here --> 
  <span id="notifications-count">3</span>
</button>  

<div role="tooltip" id="notifications-label">Notifications</div>

Providing contextual description

If your tooltip provides a contextual description of the icon, you should use aria-describedby. But, when you do this, you also need to provide an accessible name for the icon.

In this case, Heydon recommends including the label as the text content of the button. This label would be hidden visually from sighted users but read for screen readers.

Then, you can add aria-describedby to include the auxiliary description.

<button class="notifications" aria-describedby="notifications-desc">  
  <!-- icon for bell here --> 
  <span id="notifications-count">3</span> 
  <span class="visually-hidden">Notifications</span>
</button>  

<div role="tooltip" id="notifications-desc">View and manage notifications settings</div> 

Here, screen readers would say “3 notifications” first, followed by “view and manage notifications settings” after a brief pause.

Additional tooltip dos and don’ts

Here are a couple of additional points you should be aware of:

Do:

  • Use aria-labellebdy or aria-describedby attributes depending on the type of tooltip you’re building.
  • Use the tooltip role even if it

In this article, I try to summarize the best practices mentioned by various accessibility experts and their work (like this, this, and this) into a single article that’s easy to read, understand, and apply.

Let’s begin.

What are tooltips?

Tooltips are used to provide simple text hints for UI controls. Think of them as tips for tools. They’re basically little bubbles of text content that pop up when you hover over an unnamed control (like the bell icon in Stripe).

The “Notifications” text that pops up when you hover over Stripe’s bell icon is a tooltip.

If you prefer more of a formal definition, Sarah Highley provides us with a pretty good one:

A “tooltip” is a non-modal (or non-blocking) overlay containing text-only content that provides supplemental information about an existing UI control. It is hidden by default, and becomes available on hover or focus of the control it describes.

She further goes on to say:

That definition could even be narrowed down even further by saying tooltips must provide only descriptive text.

This narrowed definition is basically (in my experience) how every accessibility expert defines tooltips:

Heydon Pickering takes things even further, saying: If you’re thinking of adding interactive content (even an ok button), you should be using dialog instead.

In his words:

You’re thinking of dialogs. Use a dialog.

Two kinds of tooltips

Tooltips are basically only used for two things:

  1. Labeling an icon
  2. Providing a contextual description of an icon

Heydon separates these cleanly into two categories, “Primary Label” and “Auxiliary description” in his Inclusive Components article on tooltips and toggletips).

Two examples of a bell icon with content displayed beneath them, one as a primary label and one as an auxiliary description.

Labeling

If your tooltip is used to label an icon — using only one or two words — you should use the aria-labelledby attribute to properly label it since it is attached to nothing else on the page that would help identify it.

<button aria-labelledby="notifications"> ... </button>
<div role="tooltip" id="notifications">Notifications</div> 

You could provide contextual information, like stating the number of notifications, by giving a space-separated list of ids to aria-labelledby.

Bell icon with a badge indicating three notifications and a tooltip displayed to the right.
<button aria-labelledby="notifications-count notifications-label">  
  <!-- bell icon here --> 
  <span id="notifications-count">3</span>
</button>  

<div role="tooltip" id="notifications-label">Notifications</div>

Providing contextual description

If your tooltip provides a contextual description of the icon, you should use aria-describedby. But, when you do this, you also need to provide an accessible name for the icon.

In this case, Heydon recommends including the label as the text content of the button. This label would be hidden visually from sighted users but read for screen readers.

Then, you can add aria-describedby to include the auxiliary description.

<button class="notifications" aria-describedby="notifications-desc">  
  <!-- icon for bell here --> 
  <span id="notifications-count">3</span> 
  <span class="visually-hidden">Notifications</span>
</button>  

<div role="tooltip" id="notifications-desc">View and manage notifications settings</div> 

Here, screen readers would say “3 notifications” first, followed by “view and manage notifications settings” after a brief pause.

Additional tooltip dos and don’ts

Here are a couple of additional points you should be aware of:

Do:

Don’t:

  • Don’t use the title attribute. Much has been said about this so I shall not repeat them.
  • Don’t use the aria-haspopup attribute with the tooltip role because aria-haspopup signifies interactive content while tooltip should contain non-interactive content.
  • Don’t include essential content inside tooltips because some screen readers may ignore aria-labelledby or aria-describedby. (It’s rare, but possible.)

Tooltip limitations and alternatives

Tooltips are inaccessible to most touch devices because:

  • users cannot hover over a button on a touch device, and
  • users cannot focus on a button on a touch device.

The best alternative is not to use tooltips, and instead, find a way to include the label or descriptive text in the design.

If the “tooltip” contains a lot of content — including interactive content — you may want to display that information with a Toggletip (or just use a element).

Heydon explains toggletips nicely and concisely:

Toggletips exist to reveal information balloons. Often they take the form of little “i” icons.

Information icon with a message displayed to its right as a notification.

These informational icons should be wrapped within a

Categories: Designing, Others Tags:

15 Best New Fonts, October 2024

October 28th, 2024 No comments

Welcome to our roundup of the best new fonts we’ve found online in the last four weeks. In this month’s selection we have a mixture of different styles, from highly practical serifs, to experimental display typefaces. Enjoy!

Categories: Designing, Others Tags:

15 Best New Fonts, October 2024

October 28th, 2024 No comments
GT Flaire

GT Flaire

GT Flaire aims to translate the bold expressive curves of calligraphy into digital form. It blends profesionalism with a lively, playful style to bridge the gap between business and creativity. It’s an excellent choice for corporations hoping to create a more relaxed brand image.

Paramount Rounded

Paramount Rounded is a humanist-geometric typeface blending neo-futuristic style with geometric traditions. Featuring versatile alternates, it adapts from sleek spaceship branding to everyday packaging. Also available in a regular, non-rounded version, Paramount Rounded is a great option for branding.

Wulkan

Wulkan was designed a decade ago when the designer needed an expressive serif, couldn’t find one, and ended up creating his own. It started out as a display font; the latest iteration is a complete redesign that includes text and heading variations, new weights, and variable font options.

Wulkan

Groutpix

Groutpix is an extreme pixel-based font that references the graphics in dance music. It works best in small doses, with wide letter-spacing. It would be an excellent logo font for the right combination of letters.

Groutpix

Callas

Callas is a high-contrast typeface with a fresh, lively appearance, blending classic forma with the elegance of modernist styles. Its design is distinguished and crisp, offering a clean look with a hint of extravagance, ideal for refined yet expressive typography.

Callas

Gelatic

Gelatic is a vibrant display sans with a sunny outlook. The playful, positive shapes are ideal for relaxed, friendly logotypes. There are six styles and a variable font option for flexibility.

Gelatic

Zybo Pop

Zybo Pop is a playful, bubble-style graffiti font that delivers a bold, confident aesthetic to any project. It‘s amazing that a style that dates back to the late 1970s can still feel fresh and young, but it does. It’s a great choice for editorials, posters, and lifestyle branding.

Zybo Pop

RT Dromo

RT Dromo is a geometric sans that was inspired by vintage 1980s concert tickets. It combines robust, functional shapes with contemporary digital aesthetics for a balanced, retro-charm. It’s available in 16 fonts across four weights, including italics and monospace styles.

RT Dromo

Aukio

Aukio, which means “square” in Finnish, is a high-contrast display typeface inspired by Nordic calligraphy. Its angular, squarish forms blend traditional humanistic shapes with a digital approach, creating a contemporary design suited for striking titles.

Aukio

Apex Bound

Apex Bound is an graffiti font with Solid, Outline, Inner Shadow and Extrude styles that allow you to create depth, volume and definition for dynamic street art-style typography.

Apex Bound

Melun

Melun is a geometric sans-serif with retro flair. It comes in three distinct styles: Normal, High, and Display, each with a range of different weights and accompany italics. It has a futuristic quality that makes it excellent for posters and editorial work.

Melun

Editora

Editora is a modern take on neoclassical styles. Designed for editorial design where elegance is required. Editora has 18 styles, with a range of weights, making it as practical as it is charming.

Editora

Julia

Julia is a cursive font that blends elegance, fluidity, and readability. Its refined loops, swashes and clean forms create a modern take on a classic look. It’s currently only available in a Light weight, but more weights are on the way.

Julia

Pulso

Pulso is one of DSType’s Next Fonts project — essentially beta releases of upcoming fonts. Designed for demanding display conditions, from screens to print, Pulso features three weights plus italics, and large text versions. Pulso will be finalised in 2025 with full language support but you can get early access now.

Pulso

Fox Gavin

Fox Gavin is a playful font that’s excellent for children’s branding. It comes in four styles for layering and is perfect for display type, logos, T-shirts, and any time you need an eye-catching, friendly typeface.

Fox Gavin
Categories: Designing, Others Tags:

Come to the light-dark() Side

October 25th, 2024 No comments

You’d be forgiven for thinking coding up both a dark and a light mode at once is a lot of work. You have to remember @media queries based on prefers-color-scheme as well as extra complications that arise when letting visitors choose whether they want light or dark mode separately from the OS setting. And let’s not forget the color palette itself! Switching from a “light” mode to a “dark” mode may involve new variations to get the right amount of contrast for an accessible experience.

It is indeed a lot of work. But I’m here to tell you it’s now a lot simpler with modern CSS!

Default HTML color scheme(s)

We all know the “naked” HTML theme even if we rarely see it as we’ve already applied a CSS reset or our favorite boilerplate CSS before we even open localhost. But here’s a news flash: HTML doesn’t only have the standard black-on-white theme, there is also a native white-on-black version.

We have two color schemes available to use right out of the box!

If you want to create a dark mode interface, this is a great base to work with and saves you from having to account for annoying details, like dark inputs, buttons, and other interactive elements.

Screenshot of two forms, one with elements and background on light mode, the other all in dark mode.
Live Demo on CodePen

Switching color schemes automatically based on OS preference

Without any @media queries — or any other CSS at all — if all we did was declare color-scheme: light dark on the root element, the page will apply either the light or dark color scheme automatically by looking at the visitor’s operating system (OS) preferences. Most OSes have a built-in accessibility setting for your preferred color scheme — “light”, “dark”, or even “auto” — and browsers respect that setting.

html {
  color-scheme: light dark;
}

We can even accomplish this without CSS directly in the HTML document in a tag:

<meta name="color-scheme" content="light dark">

Whether you go with CSS or the HTML route, it doesn’t matter — they both work the same way: telling the browser to make both light and dark schemes available and apply the one that matches the visitor’s preferences. We don’t even need to litter our styles with prefers-color-scheme instances simply to swap colors because the logic is built right in!

You can apply light or dark values to the color-scheme property. At the same time, I’d say that setting color-scheme: light is redundant, as this is the default color scheme with or without declaring it.

You can, of course, control the tag or the CSS property with JavaScript.

There’s also the possibility of applying the color-scheme property on specific elements instead of the entire page in one fell swoop. Then again, that means you are required to explicitly declare an element’s color and background-color properties; otherwise the element is transparent and inherits its text color from its parent element.

What values should you give it? Try:

Default text and background color variables

The “black” colors of these native themes aren’t always completely black but are often off-black, making the contrast a little easier on the eyes. It’s worth noting, too, that there’s variation in the blackness of “black” between browsers.

What is very useful is that this default not-pure-black and maybe-not-pure-white background-color and text color are available as variables. They also flip their color values automatically with color-scheme!

They are: Canvas and CanvasText.

These two variables can be used anywhere in your CSS to call up the current default background color (Canvas) or text color (CanvasText) based on the current color scheme. If you’re familiar with the currentColor value in CSS, it seems to function similarly. CanvasText, meanwhile, remains the default text color in that it can’t be changed the way currentColor changes when you assign something to color.

In the following examples, the only change is the color-scheme property:

Screenshot of code and output area with color-scheme set to light, a large div of background color Canvas with text within set to color CanvasText, and a div within that with the Canvas and CanvasText switched.
Screenshot of code and output area with color-scheme set to dark, the rest of the code is all the same, and the light and dark areas have switched.

Not bad! There are many, many more of these system variables. They are case-insensitive, often written in camelCase or PascalCase for readability. MDN lists 19 variables and I’m dropping them in below for reference.

Open to view 19 system color names and descriptions
  • AccentColor: The background color for accented user interface controls
  • AccentColorText: The text color for accented user interface controls
  • ActiveText: The text color of active links
  • ButtonBorder: The base border color for controls
  • ButtonFace: The background color for controls
  • ButtonText: The text color for controls
  • Canvas: The background color of an application’s content or documents
  • CanvasText: The text color used in an application’s content or documents
  • Field: The background color for input fields
  • FieldText: The text color inside form input fields
  • GrayText: The text color for disabled items (e.g., a disabled control)
  • Highlight: The background color for selected items
  • HighlightText: The text color for selected items
  • LinkText: The text color used for non-active, non-visited links
  • Mark: The background color for text marked up in a element
  • MarkText: The text color for text marked up in a element
  • SelectedItem: The background color for selected items (e.g., a selected checkbox)
  • SelectedItemText: The text color for selected items
  • VisitedText: The text visited links

Cool, right? There are many of them! There are, unfortunately, also discrepancies as far as how these color keywords are used and rendered between different OSes and browsers. Even though “evergreen” browsers arguably support all of them, they don’t all actually match what they’re supposed to, and fail to flip with the CSS color-scheme property as they should.

Egor Kloos (also known as dutchcelt) is keeping an eye on the current status of system colors, including which ones exist and the browsers that support them, something he does as part of a classless CSS framework cleverly called system.css.

CodePen Embed Fallback

Declaring colors for both modes together

OK good, so now you have a page that auto-magically flips dark and light colors according to system preferences. Whether you choose to use these system colors or not is up to you. I just like to point out that “dark” doesn’t always have to mean pure “black” just as “light” doesn’t have to mean pure “white.” There are lots more colors to pair together!

But what’s the best or simplest way to declare colors so they work in both light and dark mode?

In my subjective reverse-best order:

Third place: Declare color opacity

You could keep all the same background colors in dark and light modes, but declare them with an opacity (i.e. rgb(128 0 0 / 0.5) or #80000080). Then they’ll have the Canvas color shine through.

It’s unusable in this way for text colors, and you may end up with somewhat muted colors. But it is a nice easy way to get some theming done fast. I did this for the code blocks on this old light and dark mode demo.

Screenshot of a website split into its dark and light modes, showing code blocks with gentle background colors split across both

Second place: Use color-mix()

Like this:

color-mix(in oklab, Canvas 75%, RebeccaPurple);

Similar (but also different) to using opacity to mute a color is mixing colors in CSS. We can even mix the system color variables! For example, one of the colors can be either Canvas or CanvasText so that the background color always mixes with Canvas and the text color always mixes with CanvasText.

We now have the CSS color-mix() function to help us with this. The first argument in the function defines the color space where the color mixing happens. For example, we can tell the function that we are working in the OKLAB color space, which is a rectangular color space like sRGB making it ideal to mix with sRGB color values for predictable results. You can certainly mix colors from different color spaces — the OKLAB/sRGB combination happens to work for me in this instance.

The second and third arguments are the colors you want to mix, and in what proportion. Proportions are optional but expressed in percentages. Without declaring a proportion, the mix is an even 50%-50% split. If you add percentages for both colors and they don’t match up to 100%, it does a little math for you to prevent breakages.

The color-mix() approach is useful if you’re happy to keep the same hues and color saturations regardless of whether the mode is light or dark.

A screenshot of whimsica11y.net, where the color-mix() method for making the theme is in use

In this example, as you change the value of the hue slider, you’ll see color changes in the themed boxes, following the theme color but mixed with Canvas and CanvasText:

CodePen Embed Fallback

You may have noticed that I used OKLCH and HSL color spaces in that last example. You may also have noticed that the HSL-based theme color and the themed paragraph were a lot more “flashy” as you moved the hue slider.

I’ve declared colors using a polar color space, like HSL, for years, loving that you can easily take a hue and go up or down the saturation and lightness scales based on need. But, I concede that it’s problematic if you’re working with multiple hues while trying to achieve consistent perceived lightness and saturation across them all. It can be difficult to provide ample contrast across a spectrum of colors with HSL.

The OKLCH color space is also polar just like HSL, with the same benefits. You can pick your hue and use the chroma value (which is a bit like saturation in HSL) and the lightness scales accurately in the same way. Both OKLCH and OKLAB are designed to better match what our eyes perceive in terms of brightness and color compared to transitioning between colors in the sRGB space.

While these color spaces may not explicitly answer the age-old question, Is my blue the same as your blue? the colors are much more consistent and require less finicking when you decide to base your whole website’s palette on a different theme color. With these color spaces, the contrasts between the computed colors remain much the same.

First place (winner!): Use light-dark()

Like this:

light-dark(lavender, saddlebrown);

With the previous color-mix() example, if you choose a pale lavender in light mode, its dark mode counterpart is very dark lavender.

The light-dark() function, conversely, provides complete control. You might want that element to be pale lavender in light mode and a deep burnt sienna brown in dark mode. Why not? You can still use color-mix() within light-dark() if you like — declare the colors however you like, and gain much more fine-grained control over your colors.

Feel free to experiment in the following editable demo:

CodePen Embed Fallback

Using color-scheme: light dark; — or the corresponding meta tag in HTML on your page —is a prerequisite for the light-dark() function because it allows the function to respect a person’s system preference, or whichever single light or dark value you have set on color-scheme.

Another consideration is that light-dark() is newly available across browsers, with just over 80% coverage across all users at the time I’m writing this. So, you might consider including a fallback in your CSS for browsers that lack support for the function.

What makes using color-scheme and light-dark() better than using @media queries?

@media queries have been excellent tools, but using them to query prefers-color-scheme only ever follows the preference set within the person’s operating system. This is fine until you (rightfully) want to offer the visitor more choices, decoupled from whether they prefer the UI on their device to be dark or light.

We’re already capable of doing that, of course. We’ve become used to a lot of jiggery-pokery with extra CSS classes, using duplicated styles, or employing custom properties to make it happen.

The joy of using color-scheme is threefold:

  • It gives you the basic monochrome dark mode for free!
  • It can natively do the mode switching based on OS mode preference.
  • You can use JavaScript to toggle between light and dark mode, and the colors declared in the light-dark() functions will follow it.

Light, dark, and auto mode controls

Essentially, all we are doing is setting one of three options for whether the color-scheme is light, dark, or updates auto-matically.

I advise offering all three as discrete options, as it removes some complications for you! Any new visitor to the site will likely be in auto mode because accepting the visitor’s OS setting is the least jarring default state. You then give that person the choice to stay with that or swap it out for a different color scheme. This way, there’s no need to sniff out what mode someone prefers to, for example, display the correct icon on a toggle and make it perform the correct action. There is also no need to keep an event listener on prefers-color-scheme in case of changes — your color-scheme: light dark declaration in CSS handles that for you.

Three examples of mode switches, each with the three options of Auto, Light and Dark. Buttons, a fieldset with radio buttons, and a select element.

Adjusting color-scheme in pure CSS

Yes, this is totally possible! But the approach comes with a few caveats:

  • You can’t use
  • It only works on a per page basis, not per website, which means changes are lost on reload or refresh.
  • The browser needs to support the :has() pseudo-selector. Most modern browsers do, but some folks using older devices might miss out on the experience.

Using the :has() pseudo-selector

This approach is almost alarmingly simple and is fantastic for a simple one-pager! Most of the heavy lifting is done with this:

/* default, or 'auto' */
html {
  color-scheme: light dark;
}

html:has([value="light"]:checked {
  color-scheme: light;
}

html:has([value="dark"]:checked {
  color-scheme: dark;
}

The second and third rulesets above look for an attribute called value on any element that has “light” or “dark” assigned to it, then change the color-scheme to match only if that element is :checked.

This approach is not very efficient if you have a huge page full of elements. In those cases, it’s better to be more specific. In the following two examples, the CSS selectors check for value only within an element containing id="mode-switcher".

html:has(#mode-switcher [value="light"]:checked) { color-scheme: light }
/* Did you know you don't need the ";" for a one-liner? Now you do! */

Using a element:

CodePen Embed Fallback

Using :

CodePen Embed Fallback

We could theoretically use checkboxes for this, but since checkboxes are not supposed to be used for mutually exclusive options, I won’t provide an example here. What happens in the case of more than one option being checked? The last matching CSS declaration wins (which is dark in the examples above).

Adjusting color-scheme in HTML with JavaScript

I subscribe to Jeremy Keith’s maxim when it comes to reaching for JavaScript:

JavaScript should only do what only JavaScript can do.

This is exactly that kind of situation.

If you want to allow visitors to change the color scheme using buttons, or you would like the option to be saved the next time the visitor comes to the site, then we do need at least some JavaScript. Rather than using the :has() pseudo-selector in CSS, we have a few alternative approaches for changing the color-scheme when we add JavaScript to the mix.

Using tags

If you have set your color-scheme within a meta tag in the of your HTML:

<meta name="color-scheme" content="light dark">

…you might start by making a useful constant like so:

const colorScheme = document.querySelector('meta[name="color-scheme"]');

And then you can manipulate that, assigning it light or dark as you see fit:

colorScheme.setAttribute("content", "light"); // to light mode
colorScheme.setAttribute("content", "dark"); // to dark mode
colorScheme.setAttribute("content", "light dark"); // to auto mode

This is a very similar approach to using tags but is different if you are setting the color-scheme property in CSS:

html { color-scheme: light dark; }

Instead of setting a colorScheme constant as we just did in the last example with the tag, you might select the element instead:

const html = document.querySelector('html');

Now your manipulations look like this:

html.style.setProperty("color-scheme", "light"); // to light mode
html.style.setProperty("color-scheme", "dark"); // to dark mode
html.style.setProperty("color-scheme", "light dark"); // to auto mode

I like to turn those manipulations into functions so that I can reuse them:

function switchAuto() {
  html.style.setProperty("color-scheme", "light dark");
}
function switchLight() {
  html.style.setProperty("color-scheme", "light");
}
function switchDark() {
  html.style.setProperty("color-scheme", "dark");
}

Alternatively, you might like to stay as DRY as possible and do something like this:

function switchMode(mode) {
  html.style.setProperty("color-scheme", mode === "auto" ? "light dark" : mode);
}

The following demo shows how this JavaScript-based approach can be used with buttons, radio buttons, and a element. Please note that not all of the controls are hooked up to update the UI — the demo would end up too complicated since there’s no world where all three types of controls would be used in the same UI!

CodePen Embed Fallback

I opted to use onchange and onclick in the HTML elements mainly because I find them readable and neat. There’s nothing wrong with instead attaching a change event listener to your controls, especially if you need to trigger other actions when the options change. Using onclick on a button doesn’t only work for clicks, the button is still keyboard-focusable and can be triggered with Spacebar and Enter too, as usual.

Remembering the selection for repeat visits

The biggest caveat to everything we’ve covered so far is that this only works once. In other words, once the visitor has left the site, we’re doing nothing to remember their color scheme preference. It would be a better user experience to store that preference and respect it anytime the visitor returns.

The Web Storage API is our go-to for this. And there are two available ways for us to store someone’s color scheme preference for future visits.

localStorage

Local storage saves values directly on the visitor’s device. This makes it a nice way to keep things off your server, as the stored data never expires, allowing us to call it anytime. That said, we’re prone to losing that data whenever the visitor clears cookies and cache and they’ll have to make a new selection that is freshly stored in localStorage.

You pick a key name and give it a value with .setItem():

localStorage.setItem("mode", "dark");

The key and value are saved by the browser, and can be called up again for future visits:

const mode = localStorage.getItem("mode");

You can then use the value stored in this key to apply the person’s preferred color scheme.

sessionStorage

Session storage is thrown away as soon as a visitor browses away to another site or closes the current window/tab. However, the data we capture in sessionStorage persists while the visitor navigates between pages or views on the same domain.

It looks a lot like localStorage:

sessionStorage.setItem("mode", "dark");
const mode = sessionStorage.getItem("mode");

Which storage method should I use?

Personally, I started with sessionStorage because I wanted my site to be as simple as possible, and to avoid anything that would trigger the need for a GDPR-compliant cookie banner if we were holding onto the person’s preference after their session ends. If most of your traffic comes from new visitors, then I suggest using sessionStorage to prevent having to do extra work on the GDPR side of things.

That said, if your traffic is mostly made up of people who return to the site again and again, then localStorage is likely a better approach. The convenience benefits your visitors, making it worth the GDPR work.

The following example shows the localStorage approach. Open it up in a new window or tab, pick a theme other than what’s set in your operating system’s preferences, close the window or tab, then re-open the demo in a new window or tab. Does the demo respect the color scheme you selected? It should!

CodePen Embed Fallback

Choose the “Auto” option to go back to normal.

If you want to look more closely at what is going on, you can open up the developer tools in your browser (F12 for Windows, CTRL+ click and select “Inspect” for macOS). From there, go into the “Application” tab and locate https://cdpn.io in the list of items stored in localStorage. You should see the saved key (mode) and the value (dark or light). Then start clicking on the color scheme options again and watch the mode update in real-time.

Screenshot of the top of Edge devtools, with Application tab open. The key “mode” and value “dark” saved in cdpn.io’s local storage is shown.

Accessibility

Congratulations! If you have got this far, you are considering or already providing versions of your website that are more comfortable for different people to use.

For example:

  • People with strong floaters in their eyes may prefer to use dark mode.
  • People with astigmatism may be able to focus more easily in light mode.

So, providing both versions leaves fewer people straining their eyes to access the content.

Contrast levels

I want to include a small addendum to this provision of a light and dark mode. An easy temptation is to go full monochrome black-on-white or white-on-black. It’s striking and punchy! I get it. But that’s just it — striking and punchy can also trigger migraines for some people who do a lot better with lower contrasts.

Providing high contrast is great for the people who need it. Some visual impairments do make it impossible to focus and get a sharp image, and a high contrast level can help people to better make out the word shapes through a blur. Minimum contrast levels are important and should be exceeded.

Thankfully, alongside other media queries, we can also query prefers-contrast which accepts values for no-preference, more, less, or custom.

In the following example (which uses :has() and color-mix()), a element is displayed to offer contrast settings. When “Low” is selected, a filter of contrast(75%) is placed across the page. When “High” is selected, CanvasText and Canvas are used unmixed for text color and background color:

CodePen Embed Fallback

Adding a quick high and low contrast theme gives your visitors even more choice for their reading comfort. Look at that — now you have three contrast levels in both dark and light modes — six color schemes to choose from!

ARIA-pressed

ARIA stands for Accessible Rich Internet Applications and is designed for adding a bit of extra info where needed to screen readers and other assistive tech.

The words “where needed” do heavy lifting here. It has been said that, like apostrophes, no ARIA is better than bad ARIA. So, best practice is to avoid putting it everywhere. For the most part (with only a few exceptions) native HTML elements are good to go out of the box, especially if you put useful text in your buttons!

The little bit of ARIA I use in this demo is for adding the aria-pressed attribute to the buttons, as unlike a radio group or select element, it’s otherwise unclear to anyone which button is the “active” one, and ARIA helps nicely with this use case. Now a screen reader will announce both its accessible name and whether it is in a pressed or unpressed state along with a button.

Following is an example code snippet with all the ARIA code bolded — yes, suddenly there’s lots more! You may find more elegant (or DRY-er) ways to do this, but showing it this way first makes it more clear to demonstrate what’s happening.

Our buttons have ids, which we have used to target them with some more handy consts at the top. Each time we switch mode, we make the button’s aria-pressed value for the selected mode true, and the other two false:

const html = document.querySelector("html");
const mode = localStorage.getItem("mode");
const lightSwitch = document.querySelector('#lightSwitch');
const darkSwitch = document.querySelector('#darkSwitch');
const autoSwitch = document.querySelector('#autoSwitch');

if (mode === "light") switchLight();
if (mode === "dark") switchDark();

function switchAuto() {
  html.style.setProperty("color-scheme", "light dark");
  localStorage.removeItem("mode");
  lightSwitch.setAttribute("aria-pressed","false");
  darkSwitch.setAttribute("aria-pressed","false");
  autoSwitch.setAttribute("aria-pressed","true");
}

function switchLight() {
  html.style.setProperty("color-scheme", "light");
  localStorage.setItem("mode", "light");
  lightSwitch.setAttribute("aria-pressed","true");
  darkSwitch.setAttribute("aria-pressed","false");
  autoSwitch.setAttribute("aria-pressed","false");
}

function switchDark() {
  html.style.setProperty("color-scheme", "dark");
  localStorage.setItem("mode", "dark");
  lightSwitch.setAttribute("aria-pressed","false");
  darkSwitch.setAttribute("aria-pressed","true");
  autoSwitch.setAttribute("aria-pressed","false");
}

On load, the buttons have a default setting, which is when the “Auto” mode button is active. Should there be any other mode in the localStorage, we pick it up immediately and run either switchLight() or switchDark(), both of which contain the aria-pressed changes relevant to that mode.

<button id="autoSwitch" aria-pressed="true" type="button" onclick="switchAuto()">Auto</button>
<button id="lightSwitch" aria-pressed="false" type="button" onclick="switchLight()">Light</button>
<button id="darkSwitch" aria-pressed="false" type="button" onclick="switchDark()">Dark</button>

The last benefit of aria-pressed is that we can also target it for styling purposes:

button[aria-pressed="true"] {
  background-color: transparent;
  border-width: 2px;
}

Finally, we have a nice little button switcher, with its state clearly shown and announced, that remembers your choice when you come back to it. Done!

CodePen Embed Fallback

Outroduction

Or whatever the opposite of an introduction is…

…don’t let yourself get dragged into the old dark vs light mode argument. Both are good. Both are great! And both modes are now easy to create at once. At the start of your next project, work or hobby, do not give in to fear and pick a side — give both a try, and give in to choice.

Darth Vader clenching his fist, saying “If you only knew the power of the Dark Side.”

Come to the light-dark() Side originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

Categories: Designing, Others Tags: