InstaWP Launches New Service for Disposable WordPress Testing Sites

Competition in the sandboxing products space is heating with the entrance of InstaWP, a new service for setting up disposable WordPress testing sites. Founder Vikas Singhal created the tool to provide a quick way to set up live testing sites online or to show something to a client or team.

InstaWP joins the ranks of services like TasteWP and WPSandbox but with a few unique options. At setup, users can select from WordPress versions back to 4.7 and may even choose to spin up a site using the latest beta or release candidate. Like other services, InstaWP allows you to choose your PHP version. The ability to disable WP cache and browser cache is coming soon. Users can create a custom name for their sites or leave it blank for a randomly generated name.

Free WordPress instances stay live for 8 hours, and users can link their accounts via email to extend it to 48 hours.

InstaWP, not to be confused with InstantWP, a local WordPress installation tool, was built on an nginx + Apache server without any containers. Singhal said he found containers to be too heavy for this particular use case. He runs a WordPress plugin/theme shop along with an agency on the side, both of which could benefit from InstaWP’s quick testing sites.

I wanted to build a solution for ourselves where we can quickly launch WP instances for a variety of reasons – testing a feature of WP, testing a plugin/theme, testing in different versions of WP/PHP and last but not the least – creating an ‘instant’ test environment for the clients for them to test our plugins/themes,” he said.

Singhal started InstaWP a month ago and received so much positive feedback on Reddit and from the Post Status community that he hired two dedicated developers to work on the project. Testers have commented on how fast the service spins up sites. Version 1.1.0 introduced Slack integration, which allows users to instantly set up a site by typing /wp in Slack. The release also added WordPress admin auto login for quick access without username and password.

InstaWP has a public road map. Features on deck for future releases include the following:

  1. Slack and cli commands
  2. Download Files and DB Backup from the UI
  3. Direct push to FTP or cPanel
  4. nginx and nginx + Apache configurations
  5. Finer controls on PHP settings
  6. Save configurations for instant launch of pre-configured WP
  7. Integrations with hosting providers
  8. Map custom domains
  9. Multiple servers around the world (USA, Singapore, London, etc.)

Singhal said he was aware of TasteWP as a competitor but plans to differentiate InstaWP based on simplicity and feature set.

“My vision with InstaWP is make it a default tool for WP learners, enthusiasts, freelancers, and agencies – basically everyone,” he said.

Singhal plans to monetize the tool for both end-users and plugin and theme authors. Users will have to upgrade to gain access to increased limits, custom domains, FTP access, and the ability to reserve a site. WordPress product authors can upgrade to provide 1-click demos to their clients and prospective customers.

Singhal said so far more than 500 instances have been created and teams from Yoast and some agencies are already using the tool. Several prominent WordPress businesses have requested agency pricing that would allow their users to test their plugins via a 1-click preconfigured install. The service is still under active development and Singhal plans to iron out pricing in the near future. Testers who have suggestions for InstaWP can log them on the tool’s idea board for future consideration.

Duotone Filters: WordPress 5.8 Puts a Powerful Image-Editing Tool Into Users’ Hands

Features such as the upcoming block-based widgets system, the template editor, theme-related blocks, and others have taken up much of the spotlight as of late. However, one of the best user-focused tools shipping with WordPress 5.8 is a duotone filter for Image and Cover blocks.

The term “duotone” in this sense means combining two colors as a filter. Then, layering it over an image or video. More specifically, one color is used for the shadows (dark elements), and the second color is used for the highlights (light colors).

When the feature first landed in Gutenberg 10.6 back in May, I spent a couple of hours just tinkering around with it on that first day. Since then, I have racked up a few more. It is a powerful media-editing tool that does not require users to dive into image-editing programs, allowing them to change the mood of a story at the click of a button.

Duotones can be anything from a simple grayscale to a mixture of any two colors. Shadows and highlights can even be inverted, depending on the shades chosen.

The following shows the difference between an original image of kittens (because who doesn’t love kittens?) and one with a grayscale filter:

Original image vs. grayscale duotone version.

WordPress offers a set of eight duotone color sets by default. This includes a grayscale, dark grayscale, and various combinations, making for some fun filters. Some will work better than others, often depending on the media file uploaded.

Adding a purple and yellow duotone filter over the top of an image of kittens in a field of grass.
Applying the WordPress purple and yellow duotone filter.

Like many other features awaiting users with WordPress 5.8, theme authors are those who need to dig in to offer a range of ready-baked options for users. The new theme JSON file configuration allows developers to define a set of duotone colors that match their theme.

Defining custom duotone filters is as easy as plugging a name, a slug, and two colors into a theme.json file. The theme developer handbook includes examples of creating such presets.

Custom emerald-colored duotone filter over an image of trees and sky.
Custom “emerald scale” duotone filter from a theme.

Users are not limited to the filters that WordPress or their themes offer. The duotone popover allows them to choose from any range of colors for custom shadows and highlights.

Duotone typically works best when an image has a high contrast, which means a wide-ranging spread between the light and dark colors. Darker shadows and lighter highlights make for more visually stunning filters.

When used with the Cover block, users can add filters to both image and video backgrounds. However, they also have access to the typical overlay color or gradient option. This provides a ton of flexibility for customizing media.

Applying a blue and red duotone filter along with a black, purple, and blue transparent overlay on top of an image of a record and player.
Duotone filter + gradient overlay on a Cover block.

Because the duotone feature works with an inline SVG file under the hood, it also means that using it does not permanently change image or video files. Users can still use their original media elsewhere on the site without uploading a second copy.

Duotone is just the tip of the iceberg. There are so many other possibilities outside of just laying a couple of colors on top of an image. Bence Szabó wrote an extensive tutorial on using SVG filters for patterns on CSS-Tricks. This could be a route for background options in the future — wood grain, anyone? Maybe not every possibility is suitable for core WordPress, but I would love to see plugin authors taking a stab at some alternatives.

Sort by Random – How to Randomize the Order of Rows in Google Sheets

You have a workbook in Google Sheets that contains multiple rows of data and you are required to sort the list in a random order. For instance, your sheet may contain the names of your team members and you need to reshuffle the list before assigning tasks to each of the members randomly. Or your Google Sheet may have the email addresses of people who participated in a giveaway and you need to pick any three random entries in an unbiased manner for the prize.

There are multiple ways to randomize the data rows in Google Sheet. You can either use the built-in SORT function of Google Sheets or create a menu-based function that lets you randomize data with a click.

Demo - Make a copy of this Google Sheet to try random sort with your own data in sheets.

Sort Google Sheets in Random Order

125956

Open your Google Sheet that contains the list of data and create a new sheet. Paste the following formula in A1 cell of this empty sheet.

=SORT(Customers!A2:D50, RANDARRAY(ROWS(Customers!A2:A50), 1), FALSE)

The first argument of the SORT function specifies the range of data that needs to be sorted in A1 Notation, the second argument creates a virtual column of same dimension but filled with random numbers and third order specifies the sort order from smallest to largest.

You may also want to replace Customers in the formula with the exact name of your Google Sheet. If the sheet name contains spaces, enclose your sheet name in single as quotes like 'Employee List'!A2:D50. We start with row 2 since the first row is assumed to contain the header (titles).

The advantage with this approach is that it doesn’t alter the source of data as the randomized list of data appears in a new sheet.

Sort a List Randomly in Google Sheets with Apps Script

If you prefer a more automated approach that doesn’t require you to manually add formulas each time you need to perform a random sort, take the Apps Script route.

Sort Google Sheets Randomly

Open your Google Sheet, go to the Tools menu and choose Script editor. Copy-paste the following code in the editor and save. Reload the Google Sheet and you should see a new menu as shown in the screenshot above.

/** @OnlyCurrentDoc */

// Sort data in random order
const sortRowsInRandomOrder = () => {
  // Get the current sheet that contains the list of data
  const sheet = SpreadsheetApp.getActiveSheet();

  // Get the first non-empty column
  const column = sheet.getLastColumn() + 1;

  // Add the RAND() formula to all rows in the new column
  sheet
    .getRange(1, column)
    .setFormula("=RAND()")
    .autoFillToNeighbor(SpreadsheetApp.AutoFillSeries.DEFAULT_SERIES);

  // Sort the entire range of data using the random values
  // Do not include the first row of data (header) for sort
  sheet.getDataRange().offset(1, 0).sort({ column });

  // Remove the temporary column from Google sheet
  sheet.deleteColumn(column);

  // Flush the changes
  SpreadsheetApp.flush();
};

// Add the menu to Google Sheets
const onOpen = () => {
  SpreadsheetApp.getUi()
    .createMenu("Randomize Rows")
    .addItem("Start", "sortRowsInRandomOrder")
    .addToUi();
};

Keep Shuffling Rows

Go to the Randomize Rows menu and choose Start. It creates a temporary column, fill the RAND() formula in the new column for the entire range of cells, sorts the sheet range by this data and then remove the temporary column automatically.

You can click the same menu item multiple times and it will keep shuffling the rows in random order.

10 Top Images APIs

The Internet would be a very bland place without images. Photographs, graphics, and animations are vital to enhance websites and applications in order to attract the attention of users, provide visual information, and even invoke emotions. Images aid in user experience by making an application easier to view and navigate, giving depth and context to articles, providing visualizations of products or services, and getting noticed in social media feeds or other websites.

How to Game Dev Metrics

What leads teams to game metrics within their organization?

On a recent episode of Dev Interrupted, I talked with agile expert Ray Elenteny, Principal Owner at Solutech Consulting, about how people game dev metrics and the underlying issues in culture & leadership that lead to it.

Scala Variances: Covariance, Contravariance, and Invariance

1. Variance

Variance is the interconnection of subtyping relationship between complex types and their component types.

Variance is all about sub-typing. It tells us if a type constructor is a subtype of another type constructor. Variance defines inheritance relationships of parameterized types(types that have parameters within them).

Links on React and JavaScript

As a day-job, React-using person, I like to stay abreast of interesting React news. As such, I save a healthy amount of links. Allow me to dump out my latest pile. Most of this is about React but not all of it.

  • The Plan for React 18 — A bunch of people from the React team put this post out giving us all a heads up of what’s coming. Alpha is out, beta is months away. I thought Cassidy’s article on it was the most clear about what we’re likely to care about.
  • React Query — Looks like a pretty robust tool… “the missing data-fetching library for React.” Don’t know how I missed it as it even seems more popular than Apollo. I’ve been pretty happy with using Apollo (as a user, my biggest pain is unclear error reporting), and it seems like that’s probabably the right choice if you’re heavy into GraphQL, but React Query looks awfully nice with clear docs and nice DevTools.
  • Data Fetching in Redux Made Easy With RTK Query — Matt Stobbs looks at RTK Query, which looks like yet another alternative to the Apollo / React Query stuff. Take a look at the Redux store in an app you’re working on now. If it’s anything like mine, you’ll see a mix of data from the backend (which is behaving as a cache) and UI state (the data that isn’t persisted when the page reloads). These two types of data are treated as if they are the same, which ends up making both more complicated.
  • Just-In-Time translations and code that writes itself — Dan Laush looks at a bunch of modern options for conditional and lazy loading JavaScript. This stuff is probably more complicated than it should be, but it’s getting better. Suspense in React 18 will be helpful. Top-level await is helpful. Load what you need when you need it. Astro is good at this. And, speaking of all this, Nicholas C. Zakas’ “The lazy-loading property pattern in JavaScript” is a great read with a clever pattern for defining objects that only do expensive things once, lazily when asked, then redefine that property on themselves with the result.
  • Bringing JSX to Template Literals — People think of JSX as a React thing, which is kinda fair, but it’s really a separate thing that can be useful with other frameworks (certainly Preact and even Vue). We looked at how it can be fun with even no framework at all in a previous video. Andrea Giammarchi goes deep here and shows how it can work with the already nicely-ergnomic template literals. “You can see it working in CodePen via uhtmlulandube, or lit-html.”
  • React Hooks: Compound Components — Shout out to Kent Dodds! We’ve started using this in our pattern library at CodePen. It’s been nice for keeping components a bit more consolidated rather than a sprawling tree of similarly-named sub components with hand-rolled state sharing.
  • JavaScript: What is the meaning of this? — Jake Archibald puts out the canonical article on this.
  • Human-Readable JavaScript: A Tale of Two Experts — Laurie Barth compares examples of code that do the same thing, but have different levels of readability. There isn’t always a straight answer “… but when you’re looking at code that is functionally identical, your determination should be based on humans—how humans consume code.”
  • petite-vue — jQuery was amazing and there is plenty of perfectly fine jQuery code, but the reason jQuery is a bit looked down upon these days is the messy code bases that were made with it. Some lessons were learned. While inline JavaScript handlers were once heavily scorned, nearly every popular JavaScript library today has brought them back. But let’s say something like React is too heavy-handed for you—what is the jQuery of light on-page interactivity stuff? Vue sort of walks the line between that and being more of a “big framework.” Alpine.js is probably the main player. But here comes Vue again with a poke at Alpine with a version of itself that is pretty darn small and does the same sort of stuff.

The post Links on React and JavaScript appeared first on CSS-Tricks. You can support CSS-Tricks by being an MVP Supporter.

Enterprise Messaging With Autonomous DB and Micronaut

I’ve written about messaging many times on my blog, and for good reason, too. It’s a popular subject that developers can’t seem to get enough of. In this world of distributed architectures, it’s critical that services communicate with each other to ensure the application's business logic is implemented properly. It’s well established that messaging is crucial for modern applications, so let’s look at a messaging solution that exists in the Oracle Cloud that you may not be aware of. In fact, if you’re already using Autonomous DB, then this solution is available to you at no additional charge! Allow me to introduce you to Oracle Advanced Queuing (AQ). 

What’s AQ? It’s exactly what it sounds like: a full-featured messaging solution right inside the database. Point-to-point, pub/sub, persistent, and non-persistent messaging are all supported. There are tons of ways to interact — including via PL/SQL, JMS, JDBC, .NET, Python, Node.JS — and pretty much any popular language can interface with AQ. Demos tend to be the best way to understand concepts like this, so in this post, we’re going to look at how to enable AQ in your Autonomous DB instance, create a queue, and enqueue and dequeue messages with PL/SQL. To complete the demo, we’ll look at publishing and consuming messages from AQ from a very simple Java application written with Micronaut.

Hands-on Presto Tutorial: Presto 101

In this blog we'll show you how to get started with Presto, the open source SQL query engine for the data lake. By the end you'll be able to run Presto locally on your machine.

Presto Installation

Presto can be installed manually or using docker images on:

Flutter vs React Native: What Is the Best Language for Food Delivery App Development?


Mobile apps are no longer our future; they are our reality entirely involved in our life. Spending over 90% of the smartphone time on mobile apps, they have proved to be the most efficient tool to connect to your customers and ensure they get the best experience. Mobile apps are working strategies for any segment, but with global changes happening since 2019, the on-demand economy, particularly food delivery, is now much more dependent on mobile apps. The field has skyrocketed in the past two years and needs highly productive apps to meet customer requirements. In these terms, we have searched for the best alternative platform for creating the most responsive food delivery application. And we are still facing a choice: Flutter or React Native. 

Flutter vs React Native: Why Consider Them?

Service providers have hard times deciding how to build the best experience for customers. The Food-delivery app needs to be simple and attractive. To make it happen faster with less expense, you can go for building an app from scratch or choosing a cross-platform framework. The two most popular platforms, Flutter and React Native, are the answer to the question “How to create a food delivery app?

Google Page Experience Update Tips for WordPress Sites

Google Page Experience Update Tips for WordPress SitesIf you want your website to be found by your target audience, it’s important to take Search Engine Optimization (SEO) seriously. Part of that involves staying updated on Google’s ranking signals, to ensure that your site adheres to proven best practices. Google’s Page Experience update is the latest change, and places a heavy emphasis on […]

The post Google Page Experience Update Tips for WordPress Sites appeared first on WPExplorer.

The Best States to Form an LLC

The best way to form an LLC for the majority of our readers is Incfile because of its low price and straightforward process. Register your LLC in any state starting at $0 plus state fees.

Limited liability companies (LLCs) are a popular option for entrepreneurs nationwide. Unlike other types of business structures, LLCs can be formed in any state, regardless of your company’s physical presence.

Some states offer significant financial advantages compared to others. This guide will take a closer look at the best states to form an LLC and ultimately help you determine the best state of formation for your business.

Foreign LLCs vs. Domestic LLCs

If you form an LLC in your state of residence (your home state), it’s known as a domestic LLC.

When you form an LLC somewhere other than your home state, you’re required to register that business as a foreign LLC in your home state. To be clear, the term “foreign” has nothing to do with a business being owned by a non-US resident or outside the US. It just means that the company is doing business outside of its home state.

Why is this important?

Starting an LLC in another state might require you to form two LLCs—one in the state of formation and another in your home state.

For example, let’s say you live in Indiana but want to form an LLC in Wisconsin. You’d have to register that company as a foreign LLC in Indiana to do business in your home state.

With two LLCs, you’ll have double everything. That includes two state filing fees, registered agents in both states, two annual reporting fees, and more.

Maintaining two LLCs can quickly double your costs and double your headaches.

You can dive deeper into the differences between foreign and domestic LLCs, to determine which is right for you. And if you’re not sure whether an LLC is right for your business right now, we’ve outlined the differences between an LLC and sole proprietorship and DBA vs. LLC to explain things.

Forming an LLC in Your Home State

Are some states better to form an LLC than others? Absolutely.

But for the vast majority of people, registering an LLC in your home state will be the best option.

Most people hear or read something online that says, “Nevada has no corporate income taxes,” and assume it’s the right state to form a business. While the former may be true, the latter is not always the case—especially for anyone who lives outside of Nevada. (We’ll talk about Nevada in greater detail shortly).

Why? Remember, you’ll still be required to register a foreign LLC in your home state. So, you’ll still have to pay taxes in your home state, on top of the additional fees required for maintaining two LLCs.

The idea that you can form your LLC in a “no-tax” state, elect to be taxed as a corporation, and not pay income taxes in your home state is essentially misinformation. For most people, your home state will always be the best place to form your LLC. It’s unlikely you’ll be able to save money by registering an LLC elsewhere, and it will likely cost you more money in both the short-term and long-term.

Whether you choose to form an LLC in your home state or in one of the states on this list, we recommend using an LLC formation service to help you get started. You can read our full reviews of the best LLC services here.

5 Best States to Start an LLC

With all of that in mind, five states stand out amongst the rest as the best locations to form an LLC, so if you live in one of these states—great.

If you don’t live in one of these states, don’t automatically think it’s a good idea to form an LLC here (for the reasons discussed above). The type of business you’re starting will be a factor, as well. For example, an online-only consulting business with no physical facilities or storefronts could consider forming an LLC outside of their home state. But a retailer with a physical storefront in a shopping center probably wouldn’t have as much flexibility.

Below we’ll dive deep into the pros and cons of forming an LLC in the “best” states.

1. Delaware

Delaware has a longstanding reputation for being one of the most business-friendly states in the nation. According to the Delaware Division of Corporations, nearly 67% of Fortune 500 businesses are incorporated there.

While this doesn’t necessarily apply to LLCs, it definitely conveys a draw for organizations to form a business in Delaware. In 2021, 247,003 LLCs and 24,588 LPs/LLPs (limited liability partnership) formed in Delaware compared to 62,510 corporations.

Why?

For starters, the initial state filing fees and franchise taxes are lower than other states. Delaware doesn’t impose taxes on out-of-state income, either. The filing process is simple and allows LLCs to get up and running quickly. The state keeps it easy after that, too, with online filing of LLC taxes and reports.

Image from website of Delaware Division of Corporations.
Filing annual reports and taxes for your Delaware LLC can all be done online.

Another unique standout of Delaware is the Chancery Court. This is one of three constitutional courts in Delaware (alongside the Supreme Court and Superior Court).

The Chancery Court is only for business cases. This means that business-related cases are resolved much quicker than in courts that hear cases in all categories. Plus, the judges in the Chancey Court have much more experience in business hearings.

Delaware doesn’t require shareholders, directors, or officers to be residents of the state. Furthermore, one person can be named in all of these roles. It’s also one of the only states that allows you to exclude your personal identity from the formation documents.

Pros of Forming an LLC in Delaware:

  • Quick and simple formation process
  • Low filing fees and franchise taxes
  • No corporate income taxes (foreign LLCs that elect for corporation taxing)
  • More privacy for your business
  • Flexible business structure
  • Specialized business legal system (Chancery Court)

Cons of Forming an LLC in Delaware:

  • Dual-registration required for out-of-state LLCs
  • Two registered agents required (one for each state)
  • Multiple legal representatives (most lawyers are only licensed in one state)
  • No flat franchise taxes

If you live outside of Delaware and want to form an LLC there, it could ultimately be more expensive than starting an LLC in your home state. Aside from having to maintain two LLCs, your administrative costs may also be higher. An accountant in your home state may not be familiar with Delaware structures, so you’d likely have to retain two accountants.

Need help? Visit Incfile to form an LLC in Delaware today.

2. Nevada

Nevada is another state that draws a lot of attention from business owners who want to avoid paying high taxes. That’s because Nevada doesn’t impose taxes on personal income, corporate income, or franchise taxes.

With that said, Nevada does require business owners to pay annual license fees and annual filing fees.

In terms of privacy, Nevada is arguably second to none. They are one of the only states that allow for complete anonymity with public filings. In short, your LLC can remain anonymous in any public registration filing.

Furthermore, Nevada does not have an information-sharing agreement with the IRS. Since the state doesn’t have an income tax department, there’s no information to share.

Maintaining an LLC in Nevada is easy since they don’t require annual meetings or operating agreements.

Nevada business registration overview page.
NEvada’s llc registration checklist makes it easy to follow the required steps.

The registration process is simple and also requires fewer steps compared to other states nationwide.

Pros of Forming an LLC in Nevada:

  • No state personal income or corporate taxes
  • No franchise taxes
  • LLC owners can remain anonymous
  • No information-sharing agreement with IRS
  • No operating agreements or annual meetings required

Cons of Forming an LLC in Nevada:

  • Annual business license fees
  • Annual filing fees
  • List of officers and directors is public information
  • Gross earnings over $4 million may be subject to taxes

As you can see, forming an LLC in Nevada isn’t always ideal, especially if you’re in another state. You’ll still have to create a foreign LLC in your home state and maintain two registered agents for each LLC.

Need help? Visit Incfile to form an LLC in Nevada today.

3. Wyoming

Wyoming is another state with policies aiming to be as business-friendly as possible. For starters, they don’t impose strict reporting obligations for business owners.

Similar to other states on our list, Wyoming doesn’t tax personal income or corporate income. There aren’t any franchise taxes either.

Wyoming offers something really unique compared to other states—a lifetime proxy. With a lifetime proxy, you’re able to appoint another person to represent your shares or stock in a company on your behalf. This means that business owners in Wyoming can benefit from complete anonymity.

Aside from no individual or corporate taxes, the sales tax rates in Wyoming are very low.

Sales tax by state, displayed on a map of the US.
Wyoming has some of the lowest state sales tax rates in the country.

As you can see from this graph, Wyoming ranks 44th in the country for local tax rates. Of the 46 states that impose sales tax (four states don’t have any sales tax), Hawaii and Alaska are the only two with lower averages.

Pros of Forming an LLC in Wyoming:

  • No franchise taxes
  • No corporate or personal income taxes
  • Low sales tax rates
  • Minimal reporting requirements for LLC owners
  • Lifetime proxy (for owner anonymity)

Cons of Forming an LLC in Wyoming:

  • LLC dissolution (if a member dies or files for bankruptcy)
  • High administrative costs
  • Asset protection is not guaranteed for lawsuits outside of Wyoming

Wyoming is definitely a great state to form an LLC for entrepreneurs who live in the state. But do the pros outweigh the cons if you’re living elsewhere? Your home state will still require a foreign LLC registration, so you can’t avoid taxation altogether.

Need help? Visit Incfile to form an LLC in Wyoming today.

4. Alaska

Alaska—the last frontier. While Alaska is best known for its cold weather and thousands of miles of uninhabitable terrain, it’s also a top location to form a business.

The largest state in the Union (and one of the last to join), it is an appealing place to start an LLC.

For starters, there is no state income tax or sales tax in Alaska. However, it’s worth noting that cities can collect local sales taxes (although these are generally low).

Image from City of Wasilla website explaining the local business sales tax.
Wasilla is one Alaskan city that imposes a local sales tax on businesses. However, the rate is just 2.5%.

Depending on your new business’s industry, you might be entitled to certain tax credits as well. Examples include film production credits, frontier basin credits, new area development credits, qualified oil and gas service industry expenditure credits, minerals exploration incentives, and more. However, most of these require you to actually do business within the state.

Alaska also provides new business owners with great loan programs. In October 2022, the State of Alaska, alongside the University of Alaska and the Alaska Small Business Development Center, announced the launch of a new financing program with $59.9 million in funding. These funds will be available to Alaska small businesses over the next ten years.

But similar to the tax credits, they are intended for businesses operating with a physical presence in Alaska.

The state fees associated with forming an LLC in Alaska are fairly inexpensive compared to other states. Here’s a list of some common LLC fees from the Alaska Department of Commerce, Community, and Economic Development website:

Alaska business document list with form number and fee infographic.
Registering an LLC in alaska is affordable compared to other states.

Pros of Forming an LLC in Alaska:

  • No state income taxes
  • No state sales taxes
  • Low local tax rates
  • Low LLC filing fees
  • A lot of tax credits and loan opportunities

Cons of Forming an LLC in Alaska:

  • Most credits are for businesses actually operating within Alaska
  • Local jurisdictions can collect sales tax
  • Physically distant from other states

If you live in Alaska and your business operates in Alaska, it’s definitely a great place to form an LLC. But it’s not always a practical solution for out-of-state LLC owners.

Need help? Visit Incfile to form an LLC in Alaska today.

5. South Dakota

Like other states on our list, South Dakota does not have any state income taxes (a common theme on our list).

Another advantage of starting a business in South Dakota is its 0% corporate tax rate. So, this is a great option for creating an LLC that gets taxed as a corporation. South Dakota has several other tax advantages as well, including no personal property taxes, no inheritance tax, and no business inventory tax.

The filing process is easy, affordable, and can be completed online without strict requirements.

South Dakota Secretary of State form or register a new business page.
You can file your LLC in south dakota directly from the secretary of state website.

Pros of Forming an LLC in South Dakota:

  • No state income taxes
  • 0% corporate tax rates (for LLCs taxed as corporations)
  • No business inventory tax
  • Other tax advantages (for people living in South Dakota)

Cons of Forming an LLC in South Dakota:

  • Limited life
  • Local registered agent required

Most of the advantages associated with forming an LLC in South Dakota are for state residents and companies operating within the state. Anyone else would still have to maintain a foreign LLC in their home state.

Need help? Visit Incfile to form an LLC in South Dakota today.

What to Expect When You File For an LLC

Regardless of your state of formation, there are certain expectations for LLC filing that remain constant across the board.

First, expect to pay some type of filing fee to the state. These typically range anywhere from $50 to $500, and payments are due upon filing your Articles of Organization.

Many states also require you to file an Operating Agreement. This is a legal document that explains how your LLC will be run and managed. Even if your state doesn’t require you to file an Operating Agreement during the formation process, it’s still in your best interest to do so, as it will help prevent internal conflicts amongst LLC members.

Be prepared to appoint a registered agent during the filing process as well. You could technically name yourself as the registered agent, but it will make your life much easier if you use a professional registered agent service.

Once everything has been filed, it’s just a matter of waiting until the state officially recognizes your LLC as a legal entity. The exact time varies by state, but the typical range is anywhere from three to ten business days. Most states let you expedite your filing for an additional fee, which can also be facilitated through your business formation service.

Best States to Form an LLC: Your Top Questions Answered

Conclusion

LLC formation is not universal from state to state. As you can see from this guide, some states have advantages compared to others for LLC owners.

With that said, it doesn’t mean that you should automatically form an LLC in one of these states.

So, while you may get tax breaks in one state, you’ll still have to pay them in your home state. Plus, maintaining two LLCs comes with its fair share of headaches, like extra fees, multiple accountants, multiple lawyers, and multiple registered agents.

In most cases, the pros won’t outweigh the cons when it comes to forming an LLC in a state other than your own. As always, consult with your accountant and attorney before deciding where to form an LLC.

Meta Theme Color and Trickery

Starting with Version 15, Safari supports the theme-color <meta> tag both on macOS and iOS. That’s exciting news because now the first desktop browser supports this <meta> tag and it also supports the media attribute and the prefers-color-scheme media feature.

I never really took much note of the theme-color meta tag, but now is a good time to learn about its features and limitations and try to discover some interesting use cases.

Features and limitations

Here’s how I’ve been using the theme-color meta tag for the past few years: just a good ‘ol hex code for the content attribute.

<meta name="theme-color" content="#319197">

According to tests I made earlier this year, this works in Chrome, Brave and Samsung Internet on Android, installed PWAs in Chrome and now also in Safari Technology Preview.

Hex color support is great in all supported browsers.

CSS color support

One of the first questions that came to my mind was “Can we use color keywords, hsl(), rgb(), too?” According to the HTML spec, the value of the attribute can be any CSS color. I’ve created this theme-color testing CodePen to verify that.

<meta name="theme-color" content="hsl(24.3, 97.4%, 54.3%)">
Blank webpage with orange header.
The theme-color meta tags supports CSS colors in any form: keywords, rgb(), hsl() or hex code.
Blank webpage with a hot pink header. There are controls to the right of the webpage for browser testing.
Looking at Chrome 90 on an Android Galaxy S20

All supported browsers also support hsl() and rgb(). This is awesome because it allows us to do some pretty cool stuff with JavaScript. We’ll talk about that later, but first let’s look at some limitations.

Transparency

HEX codes, rbg(), hsl() and keywords are well and consistently supported, but colors that include transparency: not so much. Actually, they are supported in most browsers, but the results aren’t very consistent and sometimes unexpected.

transparent is a CSS color and used in the theme-color meta tag most browsers do what you’d expect. All regular mobile browsers don’t change color and display the default tab bar, but Safari on macOS and the Chrome Canary PWA on macOS turn the tab bar black. The PWA on Android falls back to theme-color defined in the manifest.json, which we’ll talk about in a bit.

Examples of the same white webpage with either white or dark headers with the browser vendor labeled above each one.
Browser with a transparent theme-color meta tag

All browsers interpret hsla() and rgba(), but they set the alpha value to 1. The only exception is Safari on macOS; it interprets the transparency, but it seems like the transparent color has a black baseline. This has the effect that the light orange color looks like dark orange.

Same browser comparison but all with orange headers, except Safari which is a darker brown.
hsla() applied to the theme-color meta tag

New color functions

Safari 15 is the first browser to support lab(), lch(), and hwb() color functions. These functions work if you use them in CSS, but not if you use them in the theme-color meta tag.

All three declarations work fine in Safari 15:

body {
  background-color: hwb(27 10% 28%);
  background-color: lch(67.5345% 42.5 258.2);
  background-color: lab(62.2345% -34.9638 47.7721);
}

If you use any of the new color functions in the theme-color meta tag, Safari doesn’t interpret them and falls back to its own algorithm of picking the color. It’s likely that Safari uses the background color of your <body> for the theme-color, which means that you might get the expected result without defining the theme-color explicitly.

<meta name="theme-color" content="lab(29.2345% 39.3825 20.0664)">
Green webpage with green header.

Please be aware that at the time of writing Safari 15 is the only browser to support these new colors functions.

currentColor

If CSS colors are supported, currentColor should work, too, right? No, unfortunately not in any browser. It’s probably an uncommon use case, but I would expect that we can set the theme-color to the current color of the <body> or <html> element.

<style>
  body {
    color: blue;
  }
</style>

<meta name="theme-color" content="currentColor">

I found a ticket in the WebKit bug tracker titled <meta name="theme-color" content="..."> should also support CSS currentcolor.” Support might change in the future, if someone picks the ticket up.

Prohibited colors

When I was testing CSS color keywords, I used the color red and it didn’t work. First, I thought that keywords weren’t supported, but blue, hotpink, and green worked fine. As is turns out, there’s a narrow range of colors that Safari doesn’t support, colors that would get in the way of using the interface. red doesn’t work because it’s visually too close to the background color of the close button in the tab bar. This limitation is specific to Safari, in all other supported browsers any color seem to work fine.

Wbite webpage with a color picker set to red. The header of the browser is white.
If you set the theme-color to red, Safari uses any color it deems appropriate.

Custom properties

I don’t know enough about the internals of browsers and custom properties and if it’s even possible to access custom properties in the <head>, but I tried it anyway. Unfortunately, it didn’t work in any browser.

<style>
  :root {
    --theme: blue;
  }
</style>

<meta name="theme-color" content="var(--theme)">

That’s pretty much everything I wanted to know about basic support of the theme-color meta tag. Next, let’s see how to and how not to implement dark mode for the tab bar.

Dark mode

Safari 15 is the first desktop browser to support the media attribute and the prefers-color-scheme media feature on theme-color meta tags. Starting with version 93, Chrome supports it too, but only for installed progressive web apps.

According to the web app manifest page on web.dev, if you define multiple theme-color meta tags, browsers pick the first tag that matches.

<meta name="theme-color" content="#872e4e" media="(prefers-color-scheme: dark)">

I was eager to find out what happens in browsers that don’t support the media attribute. I’ve created a demo page for testing dark mode that includes the meta tags above and also allows you to install the site as a PWA. The webmanifest.json includes another color definition for the theme-color.

{
  "name": "My PWA",
  "icons": [
    {
      "src": "https://via.placeholder.com/144/00ff00",
      "sizes": "144x144",
      "type": "image/png"
    }
  ],
  "start_url": "/theme-color-darkmode.html",
  "display": "standalone",
  "background_color": "hsl(24.3, 97.4%, 54.3%)",
  "theme_color": "hsl(24.3, 97.4%, 54.3%)"
}

Here’s how supported browsers display the tab bar in light mode. It doesn’t matter if a browser supports the media attribute or not, it will interpret the first meta tag regardless.

Here’s how the tab bar on the same page looks like in dark mode. These results are more interesting because they vary a bit. The Canary PWA and Safari support and show the dark color. All mobile browsers use their default dark tab bar styling, except for Samsung Internet, which uses the light styling because it doesn’t support the prefers-color-scheme media feature. (TIL: This should change in the near future.)

I did one last test. I wanted to see what happens if I only define a theme color for dark mode, but access the page in light mode.

<meta name="theme-color" content="#872e4e" media="(prefers-color-scheme: dark)">

These results surprised me the most because I expected all mobile browsers to ignore the media attribute and just use the dark color in the meta tag regardless, but ordinary Chrome Canary completely ignores the whole meta tag, even though it doesn’t support the media attribute. As expected, both Canary PWAs fall back to the color defined in the manifest file.

The other interesting thing is that Safari displays a theme-color even though I haven’t defined one for light mode. That’s because Safari will pick a color on its own, if you don’t provide a theme-color. In this case, it uses the background color of the page, but it also might use the background color of the <header> element, for example.

If you want to define a theme color for light and dark mode, your best bet is to define both colors and use the first meta tag as a fallback for browsers that don’t support the media feature.

<meta name="theme-color" content="#319197" media="(prefers-color-scheme: light)">
<meta name="theme-color" content="#872e4e" media="(prefers-color-scheme: dark)">

Safari has proven that theme-color works great on desktop browsers, too. I’m sure that designers and developers will find many creative ways to use this meta tag, especially considering that the value can be changed via JavaScript. I’ve collected and created some interesting demos for your inspiration.

Demos and use cases

Theming

poolsuite.net provides different themes for the site and changes the theme-color accordingly.

Max Böck also changes the theme-color on his website when you change the theme.

Page theming

Most websites don’t provide custom themes, but you can still give your pages that certain something. Dave uses different key colors in his blog posts for links and icons, and now also in the tab bar.

Gradients

If you’re using gradients on your page, you can highlight your styling by making the gradient span the whole browser. The theme-color meta tag doesn’t support gradients, but you can use the same color for the meta tag and the start color of the gradient of you page’s background.

<meta name="theme-color" content="rgb(0, 235, 255)">

<style>
  body {
    background: linear-gradient(rgb(0, 235, 255), #08124a);
  }
</style>
Form validation

I built this proof of concept of a form that changes theme-color on form validation. It starts with a blue tab bar which turns red if the submitted data is invalid or green if it’s valid.

const email = document.querySelector('input')
const themeColor = document.querySelector('meta[name="theme-color"]')
const msg = document.querySelector('[aria-live]')
let color = '#FA0000'
let message = 'Error message'

document.querySelector('button').addEventListener('click', (e) => {
  e.preventDefault()

  email.reportValidity()
  email.setAttribute('aria-invalid', true)

  if (email.validity.valid) {
    color = '#00FF00'
    message = "Success message!"
    email.setAttribute('aria-invalid', false)
  }

  msg.textContent = message
  themeColor.setAttribute('content', color)
});
Disco mode

I’m not saying that you should, but you could put your site in 💃 Disco Mode 🕺 by combining setInterval and hsl() colors.

/*
Inspired by https://twitter.com/argyleink/status/1408184587885309952
*/

const motion = window.matchMedia("(prefers-reduced-motion: no-preference)");

// Check if users don't have a preference for reduced motion
if (motion.matches) {
  let scheme = document.querySelector('meta[name="theme-color"]')
  let hue = 0
  let color

  setInterval(() => {
    color = `hsl(${hue+=5} 50% 30%)`
    document.body.style.background = color;
    scheme.setAttribute('content', color)
  }, 50)
Scrolling

Stuart had a great idea, he suggested changing theme color on scroll. I built this quick prototype, again using hsl() colors.

Please only do this if it doesn’t affect performance negatively.

Max built a demo in which he changes the theme-color according to the background color of the current section in the viewport using Intersection Observer.

const setThemeColor = (color) => {
  const meta = document.querySelector('meta[name="theme-color"]')
  if (meta) {
    meta.setAttribute('content', color)
  }
}

if ("IntersectionObserver" in window) {
  const observer = new IntersectionObserver(entries => {
      entries.forEach(entry => {
        const { isIntersecting, target } = entry
        if (isIntersecting) {
          const color = window.getComputedStyle(target).getPropertyValue("background-color");
          setThemeColor(color)
        }
      })
  }, {
    root: document.getElementById('viewport'),
    rootMargin: "1px 0px -100% 0px",
    treshold: 0.1
  })
  
  document.querySelectorAll('.section').forEach(section => {
    observer.observe(section)
  })
}
Extracting color

Another interesting idea is to extract the dominant or average color from your header images automatically and use it as the theme-color.

<script type="module">
  import fastAverageColor from "https://cdn.skypack.dev/fast-average-color@6.4.0";
  const fac = new fastAverageColor();
    
  fac.getColorAsync(document.querySelector('img'))
    .then(color => {
      document.querySelector('meta[name="theme-color"]').setAttribute('content', color.rgba)
    })
    .catch(e => {
      console.log(e);
    });
</script> 
  
<img src="/amy-humphries-2M_sDJ_agvs-unsplash.jpg" alt="A sea star on blue sand." />

That is just a handful of ideas, but I already like where this is going and I’m sure that you’ll come up with even more creatives ways of using the theme-color meta tag.

Resources


The post Meta Theme Color and Trickery appeared first on CSS-Tricks. You can support CSS-Tricks by being an MVP Supporter.

Jamstack Community Survey 2021

(This is a sponsored post.)

The folks over at Netlify have opened up the Jamstack Community Survey for 2021. More than 3,000 front-enders like yourself took last year’s survey, which gauged how familiar people are with the term “Jamstack” and which frameworks they use.

This is the survey’s second year which is super exciting because this is where we start to reveal year-over-year trends. Will the percentage of developers who have been using a Jamstack architecture increase from last year’s 71%? Will React still be the most widely used framework, but with one of the lower satisfaction scores? Or will Eleventy still be one of the least used frameworks, but with the highest satisfaction score? Only your answers will tell!

Plus, you can qualify for a limited-edition Jamstack sticker with your response. See Netlify’s announcement for more information.

Direct Link to ArticlePermalink


The post Jamstack Community Survey 2021 appeared first on CSS-Tricks. You can support CSS-Tricks by being an MVP Supporter.

Building A Dynamic Header With Intersection Observer

The Intersection Observer API is a Javascript API that enables us to observe an element and detect when it passes a specified point in a scrolling container — often (but not always) the viewport — triggering a callback function.

Intersection Observer can be considered more performant than listening for scroll events on the main thread, as it is asynchronous, and the callback will only fire when the element we’re observing meets the specified threshold, instead every time the scroll position is updated. In this article, we’ll walk through an example of how we can use Intersection Observer to build a fixed header component that changes when it intersects with different sections of the webpage.

Basic Usage

To use Intersection Observer, we need to first create a new observer, which takes two parameters: An object with the observer’s options, and the callback function that we want to execute whenever the element we’re observing (known as the observer target) intersects with the root (the scrolling container, which must be an ancestor of the target element).

const options = {
  root: document.querySelector('[data-scroll-root]'),
  rootMargin: '0px',
  threshold: 1.0
}

const callback = (entries, observer) => {
  entries.forEach((entry) => console.log(entry))
}

const observer = new IntersectionObserver(callback, options)

When we’ve created our observer, we then need to instruct it to watch a target element:

const targetEl = document.querySelector('[data-target]')

observer.observe(targetEl)

Any of the options values can be omitted, as they will fall back to their default values:

const options = {
  rootMargin: '0px',
  threshold: 1.0
}

If no root is specified, then it will be classed as the browser viewport. The above code example shows the default values for both rootMargin and threshold. These can be hard to visualize, so are worth explaining:

rootMargin

The rootMargin value is a bit like adding CSS margins to the root element — and, just like margins, can take multiple values, including negative values. The target element will be considered to be intersecting relative to the margins.

That means that an element can technically be classed as “intersecting” even when it is out of view (if our scroll root is the viewport).

rootMargin defaults to 0px, but can take a string consisting of multiple values, just like using the margin property in CSS.

threshold

The threshold can consist of a single value or an array of values between 0 and 1. It represents the proportion of the element that must be within the root bounds for it to be considered intersecting. Using the default value of 1, the callback will fire when 100% of the target element is visible within the root.

It’s not always easy to visualize when an element will be classed as visible using these options. I’ve built a small tool to help get to grips with Intersection Observer.

Creating The Header

Now that we’ve grasped the basic principles, let’s start building our dynamic header. We’ll start with a webpage divided up into sections. This image shows the complete layout of the page we’ll be building:

I’ve included a demo at the end of this article, so feel free to jump straight to it if you’re keen to unpick the code. (There’s also a Github repository.)

Each section has a minimum height of 100vh (although they could be longer, depending on content). Our header is fixed at the top of the page and stays in place as the user scrolls (using position: fixed). The sections have different colored backgrounds, and when they meet the header, the colors of the header change to complement those of the section. There is also a marker to show the current section the user is in, which slides along when the next section arrives. To make it easier for us to get straight to the relevant code, I’ve set up a minimal demo with our starting point (before we start using the Intersection Observer API), in case you’d like to follow along.

Markup

We’ll start with the HTML for our header. This is going to be a fairly simple header with a home link and navigation, nothing especially fancy, but we’re going to use a couple of data attributes: data-header for the header itself (so we can target the element with JS), and three anchor links with the attribute data-link, which will scroll the user to the relevant section when clicked:

<header data-header>
  <nav class="header__nav">
    <div class="header__left-content">
      <a href="#0">Home</a>
    </div>
    <ul class="header__list">
      <li>
        <a href="#about-us" data-link>About us</a>
      </li>
      <li>
        <a href="#flavours" data-link>The flavours</a>
      </li>
      <li>
        <a href="#get-in-touch" data-link>Get in touch</a>
      </li>
    </ul>
  </nav>
</header>

Next, the HTML for the rest of our page, which is divided up into sections. For brevity, I’ve only included the parts relevant to the article, but the full markup is included in the demo. Each section includes a data attribute specifying the name of the background color, and an id that corresponds to one of the anchor links in the header:

<main>
  <section data-section="raspberry" id="home">
    <!--Section content-->
  </section>
  <section data-section="mint" id="about-us">
    <!--Section content-->
  </section>
  <section data-section="vanilla" id="the-flavours">
    <!--Section content-->
  </section>
  <section data-section="chocolate" id="get-in-touch">
    <!--Section content-->
  </section>
</main>

We’ll position our header with CSS so that it will stay fixed at the top of the page as the user scrolls:

header {
  position: fixed;
  width: 100%;
}

We’ll also give our sections a minimum height, and center the content. (This code isn’t necessary for the Intersection Observer to work, it’s just for the design.)

section {
  padding: 5rem 0;
  min-height: 100vh;
  display: flex;
  justify-content: center;
  align-items: center;
}

iframe Warning

While building this Codepen demo, I ran into a perplexing issue where my Intersection Observer code that should have worked perfectly was failing to fire the callback at the correct point of the intersection but instead firing when the target element intersected with the viewport edge. After a bit of head-scratching, I realized that this was because in Codepen the content is loaded within an iframe, which is treated differently. (See the section of the MDN docs on Clipping and the intersection rectangle for full details.)

As a workaround, in the demo we can wrap our markup in another element, which will act as the scrolling container — the root in our IO options — rather than the browser viewport, as we might expect:

<div class="scroller" data-scroller>
  <header data-header>
    <!--Header content-->
  </header>
  <main>
    <!--Sections-->
  </main>
</div>

If you want to see how to use the viewport as the root instead for the same demo, this is included in the Github repository.

CSS

In our CSS we’ll define some custom properties for the colors we’re using. We’ll also define two additional custom properties for the header text and background colors, and set some initial values. (We’re going to update these two custom properties for the different sections later on.)

:root {
  --mint: #5ae8d5;
  --chocolate: #573e31;
  --raspberry: #f2308e;
  --vanilla: #faf2c8;

  --headerText: var(--vanilla);
  --headerBg: var(--raspberry);
}

We’ll use these custom properties in our header:

header {
  background-color: var(--headerBg);
  color: var(--headerText);
}

We’ll also set the colors for our different sections. I’m using the data attributes as the selectors, but you could just as easily use a class if you prefer.

[data-section="raspberry"] {
  background-color: var(--raspberry);
  color: var(--vanilla);
}

[data-section="mint"]  {
  background-color: var(--mint);
  color: var(--chocolate);
}

[data-section="vanilla"] {
  background-color: var(--vanilla);
  color: var(--chocolate);
}

[data-section="chocolate"] {
  background-color: var(--chocolate);
  color: var(--vanilla);
}

We can also set some styles for our header when each section is in view:

/* Header */
[data-theme="raspberry"]  {
  --headerText: var(--raspberry);
  --headerBg: var(--vanilla);
}

[data-theme="mint"] {
  --headerText: var(--mint);
  --headerBg: var(--chocolate);
}

[data-theme="chocolate"]  {
  --headerText: var(--chocolate);
  --headerBg: var(--vanilla);
}

There’s a stronger case for using data attributes here because we’re going to toggle the data-theme attribute of the header upon each intersection.

Creating The Observer

Now that we have the basic HTML and CSS for our page set up, we can create an observer to watch for each of our sections coming into view. We want to fire a callback whenever a section comes into contact with the bottom of the header as we’re scrolling down the page. This means we need to set a negative root margin that corresponds to the height of the header.

const header = document.querySelector('[data-header]')
const sections = [...document.querySelectorAll('[data-section]')]
const scrollRoot = document.querySelector('[data-scroller]')

const options = {
  root: scrollRoot,
  rootMargin: `${header.offsetHeight * -1}px`,
  threshold: 0
}

We’re setting a threshold of 0, as we want it to fire if any part of the section is intersecting with the root margin.

First of all, we’ll create a callback to change the data-theme value of the header. (This is more straightforward than adding and removing classes, especially when our header element may have other classes applied.)

/* The callback that will fire on intersection */
const onIntersect = (entries) => {
  entries.forEach((entry) => {
    const theme = entry.target.dataset.section
    header.setAttribute('data-theme', theme)
  })
}

Then we’ll create the observer to watch for the sections intersecting:

/* Create the observer */
const observer = new IntersectionObserver(onIntersect, options)

/* Set our observer to observe each section */
sections.forEach((section) => {
  observer.observe(section)
})

Now we should see our header colors update when each section meets the header.

See the Pen Happy Face Ice Cream Parlour – Step 2 by Michelle Barker.

However, you might notice that the colors aren’t updating correctly as we scroll down. In fact, the header is updating with the previous section’s colors each time! Scrolling upwards, on the other hand, it works perfectly. We need to determine the scroll direction and change the behavior accordingly.

Finding The Scroll Direction

We’ll set a variable in our JS for the direction of scroll, with an initial value of 'up', and another for the last known scroll position (prevYPosition). Then, within the callback, if the scroll position is greater than the previous value, we can set the direction value as 'down', or 'up' if vice versa.

let direction = 'up'
let prevYPosition = 0

const setScrollDirection = () => {
  if (scrollRoot.scrollTop > prevYPosition) {
    direction = 'down'
  } else {
    direction = 'up'
  }

  prevYPosition = scrollRoot.scrollTop
}

const onIntersect = (entries, observer) => {
  entries.forEach((entry) => {
    setScrollDirection()

    /* ... */
  })
}

We’ll also create a new function to update the header colors, passing in the target section as an argument:

const updateColors = (target) => {
  const theme = target.dataset.section
  header.setAttribute('data-theme', theme)
}

const onIntersect = (entries) => {
  entries.forEach((entry) => {
    setScrollDirection()
    updateColors(entry.target)
  })
}

So far we should see no change to the behavior of our header. But now that we know the scroll direction, we can pass in a different target for our updateColors() function. If the scroll direction is up, we’ll use the entry target. If it’s down, we’ll use the next section (if there is one).

const getTargetSection = (target) => {
  if (direction === 'up') return target

  if (target.nextElementSibling) {
    return target.nextElementSibling
  } else {
    return target
  }
}

const onIntersect = (entries) => {
  entries.forEach((entry) => {
    setScrollDirection()

    const target = getTargetSection(entry.target)
    updateColors(target)
  })
}

There’s one more issue, however: the header will update not only when the section hits the header, but when the next element comes into view at the bottom of the viewport. This is because our observer fires the callback twice: once as the element is entering, and again as it’s leaving.

To determine whether the header should update, we can use the isIntersecting key from the entry object. Let’s create another function to return a boolean value for whether the header colors should update:

const shouldUpdate = (entry) => {
  if (direction === 'down' && !entry.isIntersecting) {
    return true
  }

  if (direction === 'up' && entry.isIntersecting) {
    return true
  }

  return false
}

We’ll update our onIntersect() function accordingly:

const onIntersect = (entries) => {
  entries.forEach((entry) => {
    setScrollDirection()

    /* Do nothing if no need to update */
    if (!shouldUpdate(entry)) return

    const target = getTargetSection(entry.target)
    updateColors(target)
  })
}

Now our colors should update correctly. We can set a CSS transition, so that the effect is a little nicer:

header {
  transition: background-color 200ms, color 200ms;
}

See the Pen Happy Face Ice Cream Parlour – Step 3 by Michelle Barker.

Adding The Dynamic Marker

Next we’ll add a marker to the header that updates its position as we scroll to the different sections. We can use a pseudo-element for this, so we don’t need to add anything to our HTML. We’ll give it some simple CSS styling to position it at the top left of the header, and give it a background color. We’re using currentColor for this, as it will take on the value of the header text color:

header::after {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  height: 0.4rem;
  background-color: currentColor;
}

We can use a custom property for the width, with a default value of 0. We’ll also use a custom property for the translate x value. We’re going to set the values for these in our callback function as the user scrolls.

header::after {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  height: 0.4rem;
  width: var(--markerWidth, 0);
  background-color: currentColor;
  transform: translate3d(var(--markerLeft, 0), 0, 0);
}

Now we can write a function that will update the width and position of the marker at the point of intersection:

const updateMarker = (target) => {
  const id = target.id

  /* Do nothing if no target ID */
  if (!id) return

  /* Find the corresponding nav link, or use the first one */
  let link = headerLinks.find((el) => {
    return el.getAttribute('href') === `#${id}`
  })

  link = link || headerLinks[0]

  /* Get the values and set the custom properties */
  const distanceFromLeft = link.getBoundingClientRect().left

  header.style.setProperty('--markerWidth', `${link.clientWidth}px`)
  header.style.setProperty('--markerLeft', `${distanceFromLeft}px`)
}

We can call the function at the same time we update the colors:

const onIntersect = (entries) => {
  entries.forEach((entry) => {
    setScrollDirection()

    if (!shouldUpdate(entry)) return

    const target = getTargetSection(entry.target)
    updateColors(target)
    updateMarker(target)
  })
}

We’ll also need to set an initial position for the marker, so it doesn’t just appear out of nowhere. When the document is loaded, we’ll call the updateMarker() function, using the first section as the target:

document.addEventListener('readystatechange', e => {
  if (e.target.readyState === 'complete') {
    updateMarker(sections[0])
  }
})

Finally, let’s add a CSS transition so that the marker slides across the header from one link to the next. As we’re transitioning the width property, we can use will-change to enable the browser to perform optimizations.

header::after {
  transition: transform 250ms, width 200ms, background-color 200ms;
  will-change: width;
}

Smooth Scrolling

For a final touch, it would be nice if, when a user clicks a link, they’re scrolled smoothly down the page, instead of it jumping to the section. These days we can do it right in our CSS, no JS required! For a more accessible experience, it’s a good idea to respect the user's motion preferences by only implementing smooth scrolling if they haven’t specified a preference for reduced motion in their system settings:

@media (prefers-reduced-motion: no-preference) {
  .scroller {
    scroll-behavior: smooth;
  }
}

Final Demo

Putting all the above steps together results in the complete demo.

See the Pen Happy Face Ice Cream Parlour – Intersection Observer example by Michelle Barker.

Browser Support

Intersection Observer is widely supported in modern browsers. Where necessary it can be polyfilled for older browsers — but I prefer to take a progressive enhancement approach where possible. In the case of our header, it would not be vastly detrimental to the user experience to provide a simple, unchanging version for non-supporting browsers.

To detect if Intersection Observer is supported, we can use the following:

if ('IntersectionObserver' in window && 'IntersectionObserverEntry' in window && 'intersectionRatio' in window.IntersectionObserverEntry.prototype) {
  / Code to execute if IO is supported /
} else {
  / Code to execute if not supported /
}

Resources

Read more about Intersection Observer:

  • Extensive documentation, with some practical examples from MDN
  • Intersection Observer visualiser tool
  • Timing Element Visibility with the Intersection Observer API – another tutorial from MDN, that looks at how IO can be used to track ad visibility
  • This article by Denys Mishunov covers some other uses for IO, including lazy-loading assets. Although that’s less necessary now (thanks to the loading attribute), there’s still plenty to learn here.

Rock the Stage with a Smooth WebGL Shader Transformation on Scroll

It’s fascinating which magical effects you can add to a website when you experiment with vertex displacement. Today we’d like to share a method with you that you can use to create your own WebGL shader animation linked to scroll progress. It’s a great way to learn how to bind shader vertices and colors to user interactions and to find the best flow.

We’ll be using Pug, Sass, Three.js and GSAP for our project.

Let’s rock!

The stage

For our flexible scroll stage, we quickly create three sections with Pug. By adding an element to the sections array, it’s easy to expand the stage.

index.pug:

.scroll__stage
  .scroll__content
    - const sections = ['Logma', 'Naos', 'Chara']
      each section, index in sections
        section.section
          .section__title
            h1.section__title-number= index < 9 ? `0${index + 1}` : index + 1

            h2.section__title-text= section

          p.section__paragraph The fireball that we rode was moving – But now we've got a new machine – They got music in the solar system
            br
            a.section__button Discover

The sections are quickly formatted with Sass, the mixins we will need later.

index.sass:

%top
  top: 0
  left: 0
  width: 100%

%fixed
  @extend %top

  position: fixed

%absolute
  @extend %top

  position: absolute

*,
*::after,
*::before
  margin: 0
  padding: 0
  box-sizing: border-box

.section
  display: flex
  justify-content: space-evenly
  align-items: center
  width: 100%
  min-height: 100vh
  padding: 8rem
  color: white
  background-color: black

  &:nth-child(even)
    flex-direction: row-reverse
    background: blue

  /* your design */

Now we write our ScrollStage class and set up a scene with Three.js. The camera range of 10 is enough for us here. We already prepare the loop for later instructions.

index.js:

import * as THREE from 'three'

class ScrollStage {
  constructor() {
    this.element = document.querySelector('.content')

    this.viewport = {
      width: window.innerWidth,
      height: window.innerHeight,
    }

    this.scene = new THREE.Scene()

    this.renderer = new THREE.WebGLRenderer({ 
      antialias: true, 
      alpha: true 
    })

    this.canvas = this.renderer.domElement

    this.camera = new THREE.PerspectiveCamera( 
      75, 
      this.viewport.width / this.viewport.height, 
      .1, 
      10
    )

    this.clock = new THREE.Clock()

    this.update = this.update.bind(this)

    this.init()
  }

  init() {
    this.addCanvas()
    this.addCamera()
    this.addEventListeners()
    this.onResize()
    this.update()
  }

  /**
   * STAGE
   */
  addCanvas() {
    this.canvas.classList.add('webgl')
    document.body.appendChild(this.canvas)
  }

  addCamera() {
    this.camera.position.set(0, 0, 2.5)
    this.scene.add(this.camera)
  }

  /**
   * EVENTS
   */
  addEventListeners() {
    window.addEventListener('resize', this.onResize.bind(this))
  }

  onResize() {
    this.viewport = {
      width: window.innerWidth,
      height: window.innerHeight
    }

    this.camera.aspect = this.viewport.width / this.viewport.height
    this.camera.updateProjectionMatrix()

    this.renderer.setSize(this.viewport.width, this.viewport.height)
    this.renderer.setPixelRatio(Math.min(window.devicePixelRatio, 1.5))  
  }

  /**
   * LOOP
   */
  update() {
    this.render()

    window.requestAnimationFrame(this.update) 
  }

  /**
   * RENDER
   */
  render() {
    this.renderer.render(this.scene, this.camera)
  }  
}

new ScrollStage()

We disable the pointer events and let the canvas blend.

index.sass:

...

canvas.webgl
  @extend %fixed

  pointer-events: none
  mix-blend-mode: screen

...

The rockstar

We create a mesh, assign a icosahedron geometry and set the blending of its material to additive for loud colors. And – I like the wireframe style. For now, we set the value of all uniforms to 0 (uOpacity to 1).
I usually scale down the mesh for portrait screens. With only one object, we can do it this way. Otherwise you better transform the camera.position.z.

Let’s rotate our sphere slowly.

index.js:

...

import vertexShader from './shaders/vertex.glsl'
import fragmentShader from './shaders/fragment.glsl'

...

  init() {

    ...

    this.addMesh()

    ...
  }

  /**
   * OBJECT
   */
  addMesh() {
    this.geometry = new THREE.IcosahedronGeometry(1, 64)

    this.material = new THREE.ShaderMaterial({
      wireframe: true,
      blending: THREE.AdditiveBlending,
      transparent: true,
      vertexShader,
      fragmentShader,
      uniforms: {
        uFrequency: { value: 0 },
        uAmplitude: { value: 0 },
        uDensity: { value: 0 },
        uStrength: { value: 0 },
        uDeepPurple: { value: 0 },
        uOpacity: { value: 1 }
      }
    })

    this.mesh = new THREE.Mesh(this.geometry, this.material)

    this.scene.add(this.mesh)
  }

  ...

  onResize() {

    ...

    if (this.viewport.width < this.viewport.height) {
      this.mesh.scale.set(.75, .75, .75)
    } else {
      this.mesh.scale.set(1, 1, 1)
    }

    ...

  }

  update() {
    const elapsedTime = this.clock.getElapsedTime()

    this.mesh.rotation.y = elapsedTime * .05

    ...

  }

In the vertex shader (which positions the geometry) and fragment shader (which assigns a color to the pixels) we control the values of the uniforms that we will get from the scroll position. To generate an organic randomness, we make some noise. This shader program runs now on the GPU.

/shaders/vertex.glsl:

#pragma glslify: pnoise = require(glsl-noise/periodic/3d)
#pragma glslify: rotateY = require(glsl-rotate/rotateY)

uniform float uFrequency;
uniform float uAmplitude;
uniform float uDensity;
uniform float uStrength;

varying float vDistortion;

void main() {  
  float distortion = pnoise(normal * uDensity, vec3(10.)) * uStrength;

  vec3 pos = position + (normal * distortion);
  float angle = sin(uv.y * uFrequency) * uAmplitude;
  pos = rotateY(pos, angle);    

  vDistortion = distortion;

  gl_Position = projectionMatrix * modelViewMatrix * vec4(pos, 1.);
}

/shaders/fragment.glsl:

uniform float uOpacity;
uniform float uDeepPurple;

varying float vDistortion;

vec3 cosPalette(float t, vec3 a, vec3 b, vec3 c, vec3 d) {
  return a + b * cos(6.28318 * (c * t + d));
}     

void main() {
  float distort = vDistortion * 3.;

  vec3 brightness = vec3(.1, .1, .9);
  vec3 contrast = vec3(.3, .3, .3);
  vec3 oscilation = vec3(.5, .5, .9);
  vec3 phase = vec3(.9, .1, .8);

  vec3 color = cosPalette(distort, brightness, contrast, oscilation, phase);

  gl_FragColor = vec4(color, vDistortion);
  gl_FragColor += vec4(min(uDeepPurple, 1.), 0., .5, min(uOpacity, 1.));
}

If you don’t understand what’s happening here, I recommend this tutorial by Mario Carrillo.

The soundcheck

To find your preferred settings, you can set up a dat.gui for example. I’ll show you another approach here, in which you can combine two (or more) parameters to intuitively find a cool flow of movement. We simply connect the uniform values with the normalized values of the mouse event and log them to the console. As we use this approach only for development, we do not call rAF (requestAnimationFrames).

index.js:

...

import GSAP from 'gsap'

...

  constructor() {

    ...

    this.mouse = {
      x: 0,
      y: 0
    }

    this.settings = {
      // vertex
      uFrequency: {
        start: 0,
        end: 0
      },
      uAmplitude: {
        start: 0,
        end: 0
      },
      uDensity: {
        start: 0,
        end: 0
      },
      uStrength: {
        start: 0,
        end: 0
      },
      // fragment
      uDeepPurple: {  // max 1
        start: 0,
        end: 0
      },
      uOpacity: {  // max 1
        start: 1,
        end: 1
      }
    }

    ...

  }

  addEventListeners() {

    ...

    window.addEventListener('mousemove', this.onMouseMove.bind(this))
  }

  onMouseMove(event) {
    // play with it!
    // enable / disable / change x, y, multiplier …

    this.mouse.x = (event.clientX / this.viewport.width).toFixed(2) * 4
    this.mouse.y = (event.clientY / this.viewport.height).toFixed(2) * 2

    GSAP.to(this.mesh.material.uniforms.uFrequency, { value: this.mouse.x })
    GSAP.to(this.mesh.material.uniforms.uAmplitude, { value: this.mouse.x })
    GSAP.to(this.mesh.material.uniforms.uDensity, { value: this.mouse.y })
    GSAP.to(this.mesh.material.uniforms.uStrength, { value: this.mouse.y })
    // GSAP.to(this.mesh.material.uniforms.uDeepPurple, { value: this.mouse.x })
    // GSAP.to(this.mesh.material.uniforms.uOpacity, { value: this.mouse.y })

    console.info(`X: ${this.mouse.x}  |  Y: ${this.mouse.y}`)
  }

The support act

To create a really fluid mood, we first implement our smooth scroll.

index.sass:

body
  overscroll-behavior: none
  width: 100%
  height: 100vh

  ...

.scroll
  &__stage
    @extend %fixed

    height: 100vh

  &__content
    @extend %absolute

     will-change: transform

SmoothScroll.js:

import GSAP from 'gsap'

export default class {
  constructor({ element, viewport, scroll }) {
    this.element = element
    this.viewport = viewport
    this.scroll = scroll

    this.elements = {
      scrollContent: this.element.querySelector('.scroll__content')
    }
  }

  setSizes() {
    this.scroll.height = this.elements.scrollContent.getBoundingClientRect().height
    this.scroll.limit = this.elements.scrollContent.clientHeight - this.viewport.height

    document.body.style.height = `${this.scroll.height}px`
  }

  update() {
    this.scroll.hard = window.scrollY
    this.scroll.hard = GSAP.utils.clamp(0, this.scroll.limit, this.scroll.hard)
    this.scroll.soft = GSAP.utils.interpolate(this.scroll.soft, this.scroll.hard, this.scroll.ease)

    if (this.scroll.soft < 0.01) {
      this.scroll.soft = 0
    }

    this.elements.scrollContent.style.transform = `translateY(${-this.scroll.soft}px)`
  }    

  onResize() {
    this.viewport = {
      width: window.innerWidth,
      height: window.innerHeight
    }

    this.setSizes()
  }
}

index.js:

...

import SmoothScroll from './SmoothScroll'

...

  constructor() {

    ...

    this.scroll = {
      height: 0,
      limit: 0,
      hard: 0,
      soft: 0,
      ease: 0.05
    }

    this.smoothScroll = new SmoothScroll({ 
      element: this.element, 
      viewport: this.viewport, 
      scroll: this.scroll
    })

    ...

  }

  ...

  onResize() {

    ...

    this.smoothScroll.onResize()

    ...

  }

  update() {

    ...

    this.smoothScroll.update()

    ...

  }

The show

Finally, let’s rock the stage!

Once we have chosen the start and end values, it’s easy to attach them to the scroll position. In this example, we want to drop the purple mesh through the blue section so that it is subsequently soaked in blue itself. We increase the frequency and the strength of our vertex displacement. Let’s first enter this values in our settings and update the mesh material. We normalize scrollY so that we can get the values from 0 to 1 and make our calculations with them.

To render the shader only while scrolling, we call rAF by the scroll listener. We don’t need the mouse event listener anymore.

To improve performance, we add an overwrite to the GSAP default settings. This way we kill any existing tweens while generating a new one for every frame. A long duration renders the movement extra smooth. Once again we let the object rotate slightly with the scroll movement. We iterate over our settings and GSAP makes the music.

index.js:

  constructor() {

  ...

    this.scroll = {

      ...

      normalized: 0, 
      running: false
    }

    this.settings = {
      // vertex
      uFrequency: {
        start: 0,
        end: 4
      },
      uAmplitude: {
        start: 4,
        end: 4
      },
      uDensity: {
        start: 1,
        end: 1
      },
      uStrength: {
        start: 0,
        end: 1.1
      },
      // fragment
      uDeepPurple: {  // max 1
        start: 1,
        end: 0
      },
      uOpacity: { // max 1
        start: .33,
        end: .66
      }
    }

    GSAP.defaults({
      ease: 'power2',
      duration: 6.6,
      overwrite: true
    })

    this.updateScrollAnimations = this.updateScrollAnimations.bind(this)

    ...

  }

...

  addMesh() {

  ...

    uniforms: {
      uFrequency: { value: this.settings.uFrequency.start },
      uAmplitude: { value: this.settings.uAmplitude.start },
      uDensity: { value: this.settings.uDensity.start },
      uStrength: { value: this.settings.uStrength.start },
      uDeepPurple: { value: this.settings.uDeepPurple.start },
      uOpacity: { value: this.settings.uOpacity.start }
    }
  }

  ...

  addEventListeners() {

    ...

    // window.addEventListener('mousemove', this.onMouseMove.bind(this))  // enable to find your preferred values (console)

    window.addEventListener('scroll', this.onScroll.bind(this))
  }

  ...

  /**
   * SCROLL BASED ANIMATIONS
   */
  onScroll() {
    this.scroll.normalized = (this.scroll.hard / this.scroll.limit).toFixed(1)

    if (!this.scroll.running) {
      window.requestAnimationFrame(this.updateScrollAnimations)

      this.scroll.running = true
    }
  }

  updateScrollAnimations() {
    this.scroll.running = false

    GSAP.to(this.mesh.rotation, {
      x: this.scroll.normalized * Math.PI
    })

    for (const key in this.settings) {
      if (this.settings[key].start !== this.settings[key].end) {
        GSAP.to(this.mesh.material.uniforms[key], {
          value: this.settings[key].start + this.scroll.normalized * (this.settings[key].end - this.settings[key].start)
        })
      }
    }
  }

Thanks for reading this tutorial, hope you like it!
Try it out, go new ways, have fun – dare a stage dive!

The post Rock the Stage with a Smooth WebGL Shader Transformation on Scroll appeared first on Codrops.