Deliver Knockout HTML Emails With These WordPress Plugins

There are some heavy hitters when it comes to WordPress email plugins that can help build your contact lists, send automated HTML emails, newsletters, and more. Which ones deliver the knockout punch and reign supreme as champions? Stay tuned, because we’re going to let these plugins duke it out and see who wins the title for your WordPress website.

“In this corner, weighing in on the digital scale at 16 GB of RAM is…”

We’ll be featuring some competitive email plugins that are HTML ready (to rumble). We’ll size them up and show you some specific features of each one.

By the time you get through this match, er – article – you’ll have a good idea of what will work best for you.

Dev Man fighting inbox.
Good email is worth fighting for.

Punching-out Good HTML Emails.

By default, WordPress does not send out HTML emails but sends them out as plain text. HTML emails work more consistently for your email subscribers in terms of looks and functionality.

So it’s important to have a plugin to help if you’re wanting to send your readers information via emails or newsletters that look more professional (e.g. including a logo in the signature).

Of course, to get them to opt in in the first place, they need a compelling reason why. A well-crafted message, attractive form, and specific placement on your website can do the trick.

Then, when done right, readers will opt in to and subscribe to your content.

So yes, sending professional emails instead of generic ones is important. Especially if you want to be taken seriously.

The Ultimate (In)boxing Match.

There are different divisions out there when it comes to a great WordPress email plugin, so let’s check out tonight’s matchups.

We’ll go over four very distinctive choices.

All are a bit different, all are free, and all offer various solutions to building lists, and ultimately deliver the perfect HTML emails.

So, let’s get ready to rumble!

Ding! Ding! Ding!

  • Email Posts to Subscribers

    The Email Posts to Subscribers by Gopi Ramasamy (aka Gopiplus) has great reviews and was made to automatically deliver a newsletter to subscribers that feature your latest blog posts.

    You can schedule the newsletter daily or weekly. It has 10 default templates available, or if you have the itch to create your own, it’s possible using their visual editor.

    It’s a nice “set it and forget it” plugin. Once you have it running, you won’t have to worry about scheduling your email. This automates all of that for you.

    I started by checking out their live subscription demo, entered my email, grabbed some popcorn and had ringside seats to see what it looked like when it arrived in my inbox.

    Sure enough, an email popped up shortly after hitting ‘submit’. Once I verified it, I received their welcome email.

    Nice.

    It got me excited, so let’s activate this bad boy (or girl) and check it out.

    The plugin comes up as Email Posts in the dashboard. From here, you can dig into everything it has to offer; including the General Settings, Confirmation Email, Welcome Email, and more.

    Gogiplus general settings.
    The main settings area.

    When viewing the subscribers’ area, it’s a very simple way of checking out all of your email subscribers’ information.

    Gogiplus email subscriber.

    You can create groups and organize your subscribers. It’s also nice to be able to import and export them here.

    That way, if you ever wanted to add your list to an email service like MailChimp, or add your list to your WordPress campaign, it’s very simple to do.

    Of course, to get subscribers in the first place, you need to have a way of doing that. You can manually add them into their system, or provide an opt-in box.

    The box is then added to your sidebar in the Widgets area.

    Gogiplus widget copy.
    The Email Posts to Subscribers widget. You can add as much detailed information as you’d like here.

    I made just a very simple opt-in for the sake of this demo.

    Gogiplus opt in.

    If you don’t want to add the opt-in as a widget, you also have the option of adding a shortcode to a post or page.

    And with that, we’re ready to start collecting emails!

    Now, let’s get into setting up email campaigns and more.

    When setting up your emails, there’s a list of nine pre-made templates you can choose from.

    Gogiplus email templates.
    All available email templates.
    Gogiplus preview header.
    An example of one of their pre-made templates I put together.

    You can create your own, too.

    Gogiplus mail template custom.
    An example of our own.

    In the Mail Configuration area, you can schedule your posts or newsletters to go out specifically how you would like. The Status shows you what you have set up.

    Gogiplus mail configuration.
    You can specify exactly how you’d like to have your posts sent.

    Assigning roles can simply be done in the Roles and Capabilities area.

    Once you have an email or campaign sent, they have reports worth viewing to see how they did based on open rates, status, last run, and more.
    Gogiplus email report.
    Our test campaign went out okay and we received a report back saying that it was successful.
    Gogiplus email sent report.
    For a free plugin, this one blew me away on all of the options and more that could give a major email provider a run for its money. Any automation is good, and there are even options for Google reCAPTCHA, a throttling mechanism to protect against spam submissions, and plenty more features that you’ll have to try for yourself.

    Interested in Email Posts to Subscribers?

  • Email Subscribers & Newsletters -- Simple and Effective Newsletter System

    As soon as the Email Subscribers & Newsletters — Simple and Effective Newsletter System by Icegram plugin is activated, they already have you covered.

    How?

    A welcome message stating “80% done!” and a big thumbs up appears. They’ve done a lot of the work already for you to get your email subscription in shape.

    All the essentials are included in this free plugin. If you want to take it to the next level and add a few premium options, you can upgrade and Go Pro.

    They make it simple to get started (again, they already had a lot of the legwork done) and I hopped right in.

    Everything is accessible from your dashboard under Email Subscribers.

    The first section shows your audience. It provides all of the emails, subscriptions, unsubscribes, and opens.

    Here is also where you can upload/download your contacts, create lists, sync (which will automatically subscribe a person to a specific list when opting in), and manage lists.

    Icegram audience example.
    Area of the Audience section.

    It’s very simplistic and easy to manage contacts in this area. I love how accessible it is and the straightforward information on where everything is at.

    To get contacts, we need a form for our visitors to sign up on.

    The… you guessed it – Forms section – is where you’ll go for this.

    This is the brains of the form building operations, where you can easily name, describe, adjust form fields, and more.

    Icegram edit form.
    The Edit Forms area.

    It’s a very simplistic opt-in as is. With some CSS knowledge, it can be edited accordingly with colors, style, etc.

    When you have a form completed, it will give you a shortcode that can be used on any page or blog. You can also use the Widget and place it on your page that way.

    Icegram test form.
    The test form example I set up.

    To automate emailing your newsletter and blogs, that’s another very simple feature.

    When you publish a new post, it will be emailed out automatically. It’s not quite as advanced as having weekly emails with all your posts or content sent.

    Still, it is nice to just publish a blog and know that it will go out on its own in full HTML glory.

    Icegram campaign set up.
    The Campaign area where you’ll edit post notifications.

    I set up a test email to myself and received exactly what I put down for what I wanted to include: Dev Man, of course.

    Icegram test email.
    My test email.

    There are plenty of other functions that can be tweaked and adjusted to ensure your email marketing is flawless in the Settings area.

    Icegram settings page.
    A snapshot of the Settings area.

    Here, you can set up a welcome email, confirmation email, security, and more.

    In general, this is an awesome plugin that works well with any WordPress theme. Its simplicity sets it apart (in a good way), making it as easy as ever to get an email list growing and automate your blog posts to be delivered to your readers.

    Interested in Email Subscribers & Newsletters -- Simple and Effective Newsletter System?

  • Newsletter

    The Newsletter plugin by Stefano Lissa & The Newsletter Team is an entire newsletter and email marketing system for your WordPress blog.

    It’s great for list building and you can create, send, and track HTML emails. Once activated, it packs a punch.

    When you activate, you’re welcomed by a lavish dashboard, animations, and illustrations demonstrating all of its features. It’s a nice addition and shows that they’re not some “dull and ordinary” plugin.

    Beyond visually being nice, it has all of the essential features for subscriptions to your email and/or newsletter.

    The easy to use drag and drop composer makes building newsletters simple. And with the capability of having unlimited subscribers, unlimited newsletters, advanced targeting and more, this is worth a try.

    Just having an endless amount of contacts at no cost is an advantage over professional email services that charge you based on the number of subscribers.

    Let’s check this out!

    Everything is accessible and clearly labeled right from the dashboard.

    Newsletter plugin dashboard.
    The Newsletter dashboard.

    You can see that the upper tabs have all of the ingredients you’ll need to include a subscription block and get your marketing in motion.

    Newsletter dashboard subscribers.
    From the dashboard, all the main tabs are on top.

    There are a lot of capabilities here. Going over every detail that is included in this plugin would lead to a rather long article (and not entirely necessary considering how self-explanatory this plugin is), so to keep things simple, I’ll break down just a few essentials.

    Let’s start with the Subscription Configuration. Like everything else, it’s very clear what the functions are and where they’re at.

    For example, if I want to edit the opt-in feature, I click the List Building tab, Subscription Configuration, and then all the features are right here.

    Newsletter subscription configuration.
    Where you can choose how visitors opt in, manage repeat subscriptions, override opt in, and edit notifications.

    I can see why this plugin is called Newsletter, because it truly lives up to its name as the highlight of the features — creating amazing newsletters.

    The drag and drop feature streamlines the creation process, making it incredibly easy and efficient.

    You can start by choosing a preset template. There’s everything from a simple call to action, invitation, or a big announcement.

    Or, you can create your own with some coding knowledge.

    Newsletter drag and drop feature.
    The newsletter area.

    I’m going to just create a simple call to action newsletter.

    I dragged the header block over and an image block, uploaded my own Dev Man.jpeg, and — in less than a minute — I had a newsletter ready to be delivered (possibly by Dev Man himself).

    Newsletter creator.
    As you can see, you can also preview what it will look like. Here’s an example newsletter with a mobile preview on the right.

    When you have your newsletter ready to go, it’s a matter of sending it. You can specify quite a bit in regards to how you want to compose the email.

    Newsletter email options.
    Pick from lists, select language, and plenty more.

    You can preview everything right here. It’s a simple click back to edit if you notice a change you need to make.

    To sum it all up, this is a pretty amazing plugin for the going rate of — free! There is a Premium option starting $65, which includes support, more detailed reports, and more.

    However, if you’re looking to save some money, the free version gets two thumbs (or knuckles) up from us.

  • Hustle

    Cue the music. And let’s get our groove on!

    Hustle is our very own free plugin that we created here at WPMU DEV and it can help your email marketing campaign boogie to success.

    Sure, he can dance well, but he can also pack a punch by creating pop-ups, slide-ins, ads, and sidebar widgets for your WordPress website.

    Once visitors opt in, he can then integrate with your favorite email company, where you can then create automated HTML emails, newsletters, or whatever is your favorite move.

    Not to be biased, but the simplicity of this plugin makes it probably the easiest out of all of the other examples to set up an opt-in form, widget, or slide-in for collecting emails and then reaching out.

    When you first get started, there’s a complete walkthrough on how to get moving.

    Hustle plugin for WordPress introduction.
    Hustle greets you immediately and helps you get started.

    From this point, you can choose what kind of form you want to create: Pop-up, Slide-in, Embed, or Social Share.

    Hustle create pop up.
    The Create Module.

    For this example, we’ll use a pop-up.

    I can now pick and choose various options to include in the Edit Pop-up section. You have a TON of options here to suit your needs.

    This is where you design, add what information you’d like to collect from users, integrate your favorite email provider, edit the visibility, and much more.

    All the major email services provide HTML emails, so you’ll be all set in that department. They all have customizable templates, too.

    When connecting to other apps for integration, there are 1000’s to choose from.

    Hustle email integration.
    Where you can connect your favorite apps.

    You can specify advanced features, such as animated effects on entrance and exits, delays, AdBlock, and more.

    Hustle plugin behavior.
    Example of the Behavior settings page.

    And the forms look as shiny as a disco ball. Here is an example of the pop-up I just created.

    Hustle plugin pop up example.
    Example pop-up.

    With over 80,000 installations, 4.5-star review, and ease of use, all we can say is that if you’re looking to start an amazing email marketing campaign — Hustle makes it a party.

    For more information, check out his funky video below.

And the Winner Is…

That will be for you to decide. Each one of these unique plugins can be a great match for your website.

Just remember that plain text is a lightweight to HTML when it comes to quality. A great HTML email comes across as more professional, they’re more adjustable, and the best way to showcase your message.

These customized WordPress email plugins are all prizefighters in our eyes and any one of them can be a champion for your website.

For more information on newsletter marketing, be sure to check out our post on the 7 Best Newsletter Plugins to Create and Send Emails in WordPress.

Ding! Ding! Ding!

And with that, this post is over.

JavaScript Libraries Are Almost Never Updated Once Installed

Some commentary from Zack Bloom on the Cloudflare Blog, looking at requests to CDNJS for versions of jQuery.

What we don’t see is a decline in our old versions which come close to the volume of growth of new versions when they’re released. In fact the release of 3.4.1, as popular as it quickly becomes, doesn’t change the trend of old version deprecation at all.

Sorta makes sense. We make CDNJS easy to use at CodePen, where people can quickly search for, find, and add libraries like jQuery to Pens. I very much doubt most users are rushing back to their old Pens to update versions when a new jQuery comes out.

And upgrading versions is hard and scary on large sites. I saw an Instagram from someone at Etsy (the photo is private) commemorating their upcoming upgrade off of jQuery 1.8.2, which is eight years old!

Direct Link to ArticlePermalink

The post JavaScript Libraries Are Almost Never Updated Once Installed appeared first on CSS-Tricks.

What React Does (and Doesn’t Do)

With a name as big as React, it's bound to cause some Stream-Crossing Confusion, as I like to call it. How do you center a <div> in React? Dave Ceddia:

React cares exactly zero about styling. Think of it as generating the barebones HTML. React will put elements on the page, but everything after that is the job of CSS: how they appear, what they look like, how they’re positioned, and how centered or uncentered they are.

“How to center a div in React” is… not a React problem. It’s a CSS problem. You don’t need “react” in your Google query. Once you figure it out, use React to apply the right CSS class name to your components

How do you center a <div> in WordPress? How do you center a <div> in Vue? On one hand, they are broken questions. Those technologies don't have anything to do with centering things. Centering on the web is something CSS does. On the other hand, higher-level tech is sometimes involved. Maybe there is some Gutenberg thing in WordPress that handles centering on this particular site that you should use for editorial consistency. Maybe there is some styling library being used which means you can't write regular CSS — you have to write the way the library wants you to write it. Complicated, all this "making websites" stuff.

Direct Link to ArticlePermalink

The post What React Does (and Doesn’t Do) appeared first on CSS-Tricks.

Preparing for WordPress 5.4: Changes Theme and Plugin Developers Should Know About

With the release of WordPress 5.4 looming, it is time for plugin and theme developers to begin testing their extensions and making sure there are no issues. There are also new APIs for upcoming features. Yesterday, the core team released the first release candidate for 5.4. The official release is planned for March 31.

This post will serve as a quick guide with links to several important changes that developers need to keep in mind in the coming weeks. Be sure to test your plugins and themes.

Theme Developers

Screenshot of the new social icons block in use via the block editor.
New social icons block.

There are several changes that theme authors will want to test against. WordPress 5.4 has a few extra theme features. It also has several markup-related changes that could break theme designs on the front end and in the block editor. Unfortunately, for theme authors who want to support multiple versions of WordPress, some of these changes may mean a little extra CSS bloat.

Social Icons and Buttons Blocks

WordPress 5.4 introduces two new blocks: social icons and buttons. The social icons block allows users to insert icons/links for up to 40 different social networks. The buttons block lets users group multiple button blocks together. Theme authors who are rolling out custom block editor styles need to account for these new blocks to make sure they are output correctly.

Create Custom Gradient Presets

The new Gradients API allows theme authors to define custom gradient presets for users to use with either the group or button blocks. Theme authors will need to do some legwork to improve on the eyesore that is the default gradient presets. With a little work, gradients can be a useful tool at the user’s disposal. Theme authors can also disable gradients altogether if they prefer not to support them.

Block Editor Markup and Style Changes

Theme authors who have directly targeted specific editor classes, will need to check their block editor styles. Many classes with the editor- prefix have been changed to use the block-editor- prefix. The wrapper element with the .edit-post-layout__content class has been removed altogether. Several wrapper elements were removed from blocks and the rich text component. Core’s built-in padding and negative margins on blocks have been refactored, which is a welcome addition. Perhaps theme authors will no longer have to fight against multiple nested selectors to provide a basic, working layout that matches the front end.

These changes have already broken several themes I have seen. There is a good chance many theme authors will need to update their block editor styles.

At a time when the Theme Review Team is asking for more theme authors to submit themes with custom editor styles, these types of changes to classes and markup are not a boost of confidence. Theme developers can easily feel like they are fighting a losing battle. However, work is moving forward to make the editor markup closer to a one-to-one match with the front end. At some point, theme authors can only hope they will no longer need to deal with these kinds of changes while supporting users across multiple versions of WordPress. For now, they are in a somewhat messy transitional phase.

Calendar Markup and Class Changes

The core team changed the markup of the get_calendar() function, which also affects the Calendar widget. The calendar output no longer has a <tfoot> element. Instead, the previous and next month links were moved to a <nav> element below the <table> element.

The calendar output also adds or changes multiple IDs and classes:

  • .wp-calendar-table added to the wrapper element.
  • .wp-calendar-nav added to the navigation wrapper element.
  • .wp-calendar-nav-next replaces the #next ID on the next month link.
  • .wp-calendar-nav-prev replaces the #prev ID on the previous month link.

These are breaking changes. Any custom CSS that targeted the old HTML or IDs will need to be updated.

Block Developers

Screenshot of a code editor that showcases the initial code for creating a block plugin.
Initial JavaScript file created by the block scaffolding script.

For plugin developers who are creating custom blocks, WordPress 5.4 introduces several new APIs and tools for working with the block system.

Block Scaffolding

Developers have a new NPM package for quickly creating a block plugin. With a single command of npm init @wordpress/block <plugin-name> the script will create a new directory and build out the appropriate PHP, CSS, and JavaScript files necessary for building a block plugin. Developers can use modern JavaScript tooling by default or optionally choose to use an ES5 version.

The intention of the block scaffolding package is for plugin authors to build single-block plugins that will eventually make their way into the official block directory.

Block Collections API

The Block Collections API works similarly to categories. However, they are based on namespace. When a plugin developer registers a custom collection, any blocks that share the collection namespace will appear under a custom section in the block inserter. This seems to be a smarter way to organize blocks. It will certainly come in handy for plugins that create libraries of blocks, providing an automatic way to group them together.

Block Variations API

The new Block Variations API allows block developers to essentially create copies of block with a variation. Each registered variation will appear as a separate block in the block inserter for users to choose from.

A good example of this feature is the new social icons block. It is a single block with 40 variations for the various social networks.

Other Developer-Related Changes

There are a couple of other changes of note that cross into both plugin and theme development territory.

New Nav Menu Hooks

After waiting and waiting and waiting, developers are finally getting some oft-requested hooks for adding custom fields to the nav menu admin screen and customizer. At least one ticket goes back 9 years, but it is better late than never. In the past, developers would need to use a custom walker class to make some of the necessary customizations. However, only a single walker class could be used at a time, which meant that multiple plugins that made changes would not work together.

The core team added the new wp_nav_menu_item_custom_fields hook on the nav menus admin screen, which appears before the “move” buttons for individual menu items. For parity with the admin, nav menu items have a new wp_nav_menu_item_custom_fields_customize_template in the customizer. These hooks will allow developers to add custom form fields necessary for adding custom data to nav menu items.

apply_shortcodes() Alias Function

WordPress 5.4 introduces a new apply_shortcodes() function. It is an alias for the do_shortcode() function. The new function provides a more semantically-correct function name. Generally, functions with a prefix of do_ expect output or some type of action. Functions with a prefix of apply_ expect data to be returned.

If you are creating a theme or plugin with shortcode-aware areas, you will want to make the switch to the new function. While the do_shortcode() function is not currently marked for deprecation, that should be the eventual goal.

Covid-19 Virus and N95

As if Jeff Bezos isn't already rich enough. As someone who is at high risk because of a compromised immune system, I thought it might be a good idea to get a few N95 masks. Because local medical supply stores are out of stock I checked Amazon. While the prices are reasonable (pack of 20 for $99), they want $200 for shipping. I bought some luggage a couple of years ago and because my order was over $35 the shipping was free. So how is it that something that weighs less than a box of Kleenex costs $200? Could this be a way of avoiding charges of price gouging? Keep the actual price reasonable but kill on shipping? If this is the case than Mr. Bezos could not only be the richest person alive but possibly also one of the most contemptible.

TranslateMe Releases French to English API

TranslateMe, an AI-driven decentralized translation platform, announced the release of a French to English Translation API. The API is currently free for interested parties to both test and use. While it's fully functional, the company reported that it only uses 20% of its total capability (which includes a database of 10 million French to English sentences).

#258: Keyboard Commands

Show Description

Stephen, Marie, and Chris talk about figuring out how to add new keyboard shortcuts to CodePen and the challenges it proposes trying to add features like that to a browser-based app like CodePen.

Time Jumps

Sponsor: Netlify

Netlify is the fastest way to build the fastest sites, Jamstack style. Netlify is a web host that hosts your static files, but for not-so-static sites. The static file hosting is just so that the site can be served over a global CDN as quickly and securely as is possible to do. Any kind of functionality is possible through things like built-in form processing, auth, and cloud functions, and the developer experience is second to none.

Show Links

The post #258: Keyboard Commands appeared first on CodePen Blog.

Kubernetes Explained: Part 2 — Containers

In our previous post, Kube Explained: Part 1, I described how the introduction of the cloud resulted in CI/CD, Microservices, and a massive amount of pressure to standardize backend infrastructure tooling.

In this post, we’ll cover the first and most important domino to fall in this wave of standardization: the container. For the first time, containers standardized the packaging, distribution, and lifecycle of backend services and in doing so, paved the way for container orchestration, Kubernetes, and the explosion of innovation that’s surrounded that ecosystem.

Purpose and Role of DevOps in Custom Software Development

Do you have any system of checks ensuring all the coding and testing principles are followed to the core? 

As important as this question is, equally important is seeking answers for it. If your answer to this question is a No then remember your custom software development project is at stake. 

10 Famous Apps Using React.js

Front-end development is continuously increasing by adding new tools released daily. There are several libraries and frameworks available online, and choosing one from them is quite difficult. Talking about front-end development, Angular was the default choice for many business owners, but the time has changed, and React.js is breaking records in the web development market.

What Is React?

Do you remember how Facebook and Messenger looked a few ago? You needed to refresh the entire page for new updates. But with React.js, a popup message will appear, and clicking on that will help you update automatically. As a React.js web development company, we can define React.js as one of the powerful and reliable cross-platform tools used by top companies to develop mobile applications. It mainly uses JavaScript with JSX, ES6, and major updates to JavaScript including dozens of newly added features. 

Why Is Automation the Only Way to Deliver Continuous Testing in Agile?

The use of agile methodologies for testing and development of software applications is growing rapidly. More and more businesses are adopting agile approaches in their application development cycle. That’s why most testing teams are focused on improving and enhancing their agile management.

Agile methodologies allow teams to carry out software development throughout SDLC so that bugs can be detected in the early stages of development, and developers can fix them immediately. It is being said that when agile development and testing come together, speed becomes the primary focus for both developers and testers. And it is true because for continuous delivery in agile development, implementing continuous testing in DevOps becomes critical.

Why gRPC for Inter-Microservice Communication

Hi folks! In this blog, we will understand why one should use gRPC for inter-service communication over other RESTful services.

What is gRPC?

It is a high performance, open-source, universal RPC framework. In simple words, it enables the server and client applications to communicate transparently and build connected systems. Google developed gRPC and made it available open-source. With it, a customer can directly call methods on a server application on a different machine as if it were a local object. gRPC is based on the foundations of conventional Remote Procedure Call (RPC) technology but implemented on top of the modern technology stacks such as HTTP2, protocol buffers, etc., to ensure maximum interoperability.

How We Created a Static Site That Generates Tartan Patterns in SVG

Tartan is a patterned cloth that’s typically associated with Scotland, particularly their fashionable kilts. On tartanify.com, we gathered over 5,000 tartan patterns (as SVG and PNG files), taking care to filter out any that have explicit usage restrictions.

The idea was cooked up by Sylvain Guizard during our summer holidays in Scotland. At the very beginning, we were thinking of building the pattern library manually in some graphics software, like Adobe Illustrator or Sketch. But that was before we discovered that the number of tartan patterns comes in thousands. We felt overwhelmed and gave up… until I found out that tartans have a specific anatomy and are referenced by simple strings composed of the numbers of threads and color codes.

Tartan anatomy and SVG

Tartan is made with alternating bands of colored threads woven at right angles that are parallel to each other. The vertical and horizontal bands follow the same pattern of colors and widths. The rectangular areas where the horizontal and vertical bands cross give the appearance of new colors by blending the original ones. Moreover, tartans are woven with a specific technique called twill, which results in visible diagonal lines. I tried to recreate the technique with SVG rectangles as threads here:

Let’s analyze the following SVG structure:


<svg viewBox="0 0 280 280" width="280" height="280" x="0"  y="0" xmlns="http://www.w3.org/2000/svg">
  <defs>
    <mask id="grating" x="0" y="0" width="1" height="1">
      <rect x="0" y="0" width="100%" height="100%" fill="url(#diagonalStripes)"/>
    </mask>
  </defs>
  <g id="horizontalStripes">
    <rect fill="#FF8A00" height="40" width="100%" x="0" y="0"/>    
    <rect fill="#E52E71" height="10" width="100%" x="0" y="40"/>
    <rect fill="#FFFFFF" height="10" width="100%" x="0" y="50"/>
    <rect fill="#E52E71" height="70" width="100%" x="0" y="60"/>   
    <rect fill="#100E17" height="20" width="100%" x="0" y="130"/>    
    <rect fill="#E52E71" height="70" width="100%" x="0" y="150"/>
    <rect fill="#FFFFFF" height="10" width="100%" x="0" y="220"/>
    <rect fill="#E52E71" height="10" width="100%" x="0" y="230"/>   
    <rect fill="#FF8A00" height="40" width="100%" x="0" y="240"/>
  </g>
  <g id="verticalStripes" mask="url(#grating)">
    <rect fill="#FF8A00" width="40" height="100%" x="0" y="0" />  
    <rect fill="#E52E71" width="10" height="100%" x="40" y="0" />
    <rect fill="#FFFFFF" width="10" height="100%" x="50" y="0" />
    <rect fill="#E52E71" width="70" height="100%" x="60" y="0" />
    <rect fill="#100E17" width="20" height="100%" x="130" y="0" />   
    <rect fill="#E52E71" width="70" height="100%" x="150" y="0" />
    <rect fill="#FFFFFF" width="10" height="100%" x="220" y="0" />
    <rect fill="#E52E71" width="10" height="100%" x="230" y="0" />   
    <rect fill="#FF8A00" width="40" height="100%" x="240" y="0" />
  </g>
</svg>

The horizontalStripes group creates a 280x280 square with horizontal stripes. The verticalStripes group creates the same square, but rotated by 90 degrees. Both squares start at (0,0) coordinates. That means the horizontalStripes are completely covered by the verticalStripes; that is, unless we apply a mask on the upper one.

<defs>
  <mask id="grating" x="0" y="0" width="1" height="1">
    <rect x="0" y="0" width="100%" height="100%" fill="url(#diagonalStripes)"/>
  </mask>
</defs>

The mask SVG element defines an alpha mask. By default, the coordinate system used for its x, y, width, and height attributes is the objectBoundingBox. Setting width and height to 1 (or 100%) means that the mask covers the verticalStripes resulting in just the white parts within the mask being full visible.

Can we fill our mask with a pattern? Yes, we can! Let’s reflect the tartan weaving technique using a pattern tile, like this:

In the pattern definition we change the patternUnits from the default  objectBoundingBox to userSpaceOnUse so that now, width and height are defined in pixels.

<svg width="0" height="0">
  <defs>
    <pattern id="diagonalStripes" x="0" y="0" patternUnits="userSpaceOnUse" width="8" height="8">
      <polygon points="0,4 0,8 8,0 4,0" fill="white"/>
      <polygon points="4,8 8,8 8,4" fill="white"/>
    </pattern>    
  </defs> 
</svg>

Using React for tartan weaving

We just saw how we can create a manual “weave” with SVG. Now let’s automatize this process with React. 

The SvgDefs component is straightforward — it returns the defs markup.

const SvgDefs = () => {
  return (
    <defs>
      <pattern
        id="diagonalStripes"
        x="0"
        y="0"
        width="8"
        height="8"
        patternUnits="userSpaceOnUse"
      >
        <polygon points="0,4 0,8 8,0 4,0" fill="#ffffff" />
        <polygon points="4,8 8,8 8,4" fill="#ffffff" />
      </pattern>
      <mask id="grating" x="0" y="0" width="1" height="1">
        <rect
          x="0"
          y="0"
          width="100%"
          height="100%"
          fill="url(#diagonalStripes)"
        />
      </mask>
    </defs>
  )
}

We will represent a tartan as an array of stripes. Each stripe is an object with two properties: fill (a hex color) and size (a number).

const tartan = [
  { fill: "#FF8A00", size: 40 },
  { fill: "#E52E71", size: 10 },
  { fill: "#FFFFFF", size: 10 },
  { fill: "#E52E71", size: 70 },
  { fill: "#100E17", size: 20 },
  { fill: "#E52E71", size: 70 },
  { fill: "#FFFFFF", size: 10 },
  { fill: "#E52E71", size: 10 },
  { fill: "#FF8A00", size: 40 },
]

Tartans data is often available as a pair of strings: Palette and Threadcount that could look like this:

// Palette
O#FF8A00 P#E52E71 W#FFFFFF K#100E17

// Threadcount
O/40 P10 W10 P70 K/10.

I won’t cover how to convert this string representation into the stripes array but, if you are interested, you can find my method in this Gist.

The SvgTile component takes the tartan array as props and returns an SVG structure.

const SvgTile = ({ tartan }) => {

  // We need to calculate the starting position of each stripe and the total size of the tile
  const cumulativeSizes = tartan
    .map(el => el.size)
    .reduce(function(r, a) {
      if (r.length > 0) a += r[r.length - 1]
      r.push(a)
      return r
    }, [])
  
  // The tile size
  const size = cumulativeSizes[cumulativeSizes.length - 1]

  return (
    <svg
      viewBox={`0 0 ${size} ${size}`}
      width={size}
      height={size}
      x="0"
      y="0"
      xmlns="http://www.w3.org/2000/svg"
    >
      <SvgDefs />
      <g id="horizontalStripes">
        {tartan.map((el, index) => {
          return (
            <rect
              fill={el.fill}
              width="100%"
              height={el.size}
              x="0"
              y={cumulativeSizes[index - 1] || 0}
            />
          )
        })}
      </g>
      <g id="verticalStripes" mask="url(#grating)">
        {tartan.map((el, index) => {
          return (
            <rect
              fill={el.fill}
              width={el.size}
              height="100%"
              x={cumulativeSizes[index - 1] || 0}
              y="0"
            />
          )
        })}
      </g>
    </svg>
  )
}

Using a tartan SVG tile as a background image

On tartanify.com, each individual tartan is used as a background image on a full-screen element. This requires some extra manipulation since we don’t have our tartan pattern tile as an SVG image. We're also unable to use an inline SVG directly in the background-image property.

Fortunately, encoding the SVG as a background image does work:

.bg-element {
  background-image: url('data:image/svg+xml;charset=utf-8,<svg>...</svg>');
}

Let’s now create an SvgBg component. It takes the tartan array as props and returns a full-screen div with the tartan pattern as background.

We need to convert the SvgTile React object into a string. The ReactDOMServer object allows us to render components to static markup. Its method renderToStaticMarkup is available both in the browser and on the Node server. The latter is important since later we will server render the tartan pages with Gatsby.

const tartanStr = ReactDOMServer.renderToStaticMarkup(<SvgTile tartan={tartan} />)

Our SVG string contains hex color codes starting with the # symbol. At the same time, # starts a fragment identifier in a URL. It means our code will break unless we escape all of those instances. That’s where the built-in JavaScript encodeURIComponent function comes in handy.

const SvgBg = ({ tartan }) => {
  const tartanStr = ReactDOMServer.renderToStaticMarkup(<SvgTile tartan={tartan} />)
  const tartanData = encodeURIComponent(tartanStr)
  return (
    <div
      style={{
        width: "100%",
        height: "100vh",
        backgroundImage: `url("data:image/svg+xml;utf8,${tartanData}")`,
      }}
    />
  )
}

Making an SVG tartan tile downloadable

Let’s now download our SVG image.

The SvgDownloadLink component takes svgData (the already encoded SVG string) and fileName as props and creates an anchor (<a>) element. The download attribute prompts the user to save the linked URL instead of navigating to it. When used with a value, it suggests the name of the destination file.

const SvgDownloadLink = ({ svgData, fileName = "file" }) => {
  return (
    <a
      download={`${fileName}.svg`}
      href={`data:image/svg+xml;utf8,${svgData}`}
    >
      Download as SVG
    </a>
  )
}

Converting an SVG tartan tile to a high-res PNG image file

What about users that prefer the PNG image format over SVG? Can we provide them with high resolution PNGs?

The PngDownloadLink component, just like SvgDownloadLink, creates an anchor tag and has the tartanData and fileName as props. In this case however, we also need to provide the tartan tile size since we need to set the canvas dimensions.

const Tile = SvgTile({tartan})
// Tartan tiles are always square
const tartanSize = Tile.props.width

In the browser, once the component is ready, we draw the SVG tile on a <canvas> element. We’ll use the canvas toDataUrl() method that returns the image as a data URI. Finally, we set the date URI as the href attribute of our anchor tag.

Notice that we use double dimensions for the canvas and double scale the ctx. This way, we will output a PNG that’s double the size, which is great for high-resolution usage.

const PngDownloadLink = ({ svgData, width, height, fileName = "file" }) => {
  const aEl = React.createRef()
  React.useEffect(() => {
    const canvas = document.createElement("canvas")
    canvas.width = 2 * width
    canvas.height = 2 * height
    const ctx = canvas.getContext("2d")
    ctx.scale(2, 2)
    let img = new Image()
    img.src = `data:image/svg+xml, ${svgData}`
    img.onload = () => {
      ctx.drawImage(img, 0, 0)
      const href = canvas.toDataURL("image/png")
      aEl.current.setAttribute("href", href)
    }
  }, [])
  return (
    <a 
      ref={aEl} 
      download={`${fileName}.png`}
    >
      Download as PNG
    </a>
  )
}

For that demo, I could have skipped React's useEffect hook and the code would worked fine. Nevertheless, our code is executed both on the server and in the browser, thanks to Gatsby. Before we start creating the canvas, we need to be sure that we are in a browser. We should also make sure the anchor element is ”ready” before we modify its attribute. 

Making a static website out of CSV with Gatsby

If you haven’t already heard of Gatsby, it’s a free and open source framework that allows you to pull data from almost anywhere and generate static websites that are powered by React.

Tartanify.com is a Gatsby website coded by myself and designed by Sylvain. At the beginning of the project, all we had was a huge CSV file (seriously, 5,495 rows), a method to convert the palette and threadcount strings into the tartan SVG structure, and an objective to give Gatsby a try.

In order to use a CSV file as the data source, we need two Gatsby plugins: gatsby-transformer-csv and gatsby-source-filesystem. Under the hood, the source plugin reads the files in the /src/data folder (which is where we put the tartans.csv file), then the transformer plugin parses the CSV file into JSON arrays.

// gatsby-config.js
module.exports = {
  /* ... */
  plugins: [
    'gatsby-transformer-csv',
    {
      resolve: 'gatsby-source-filesystem',
      options: {
        path: `${__dirname}/src/data`,
        name: 'data',
      },
    },
  ],
}

Now, let’s see what happens in the gatsby-node.js file. The file is run during the site-building process. That’s where we can use two Gatsby Node APIs: createPages and onCreateNode. onCreateNode is called when a new node is created. We will add two additional fields to a tartan node: its unique slug and a unique name. It is necessary since the CSV file contains a number of tartan variants that are stored under the same name.

// gatsby-node.js
// We add slugs here and use this array to check if a slug is already in use
let slugs = []
// Then, if needed, we append a number
let i = 1

exports.onCreateNode = ({ node, actions }) => {
  if (node.internal.type === 'TartansCsv') {
    // This transforms any string into slug
    let slug = slugify(node.Name)
    let uniqueName = node.Name
    // If the slug is already in use, we will attach a number to it and the uniqueName
    if (slugs.indexOf(slug) !== -1) {
      slug += `-${i}`
      uniqueName += ` ${i}`
      i++
    } else {
      i = 1
    }
    slugs.push(slug)
  
    // Adding fields to the node happen here
    actions.createNodeField({
      name: 'slug',
      node,
      value: slug,
    })
    actions.createNodeField({
      name: 'Unique_Name',
      node,
      value: uniqueName,
    })
  }
}

Next, we create pages for each individual tartan. We want to have access to its siblings so that we can navigate easily. We will query the previous and next edges and add the result to the tartan page context.

// gatsby-node.js
exports.createPages = async ({ graphql, actions }) => {
  const { createPage } = actions
  const allTartans = await graphql(`
    query {
      allTartansCsv {
        edges {
          node {
            id
            fields {
              slug
            }
          }
          previous {
            fields {
              slug
              Unique_Name
            }
          }
          next {
            fields {
              slug
              Unique_Name
            }
          }
        }
      }
    }
  `)
  if (allTartans.errors) {
    throw allTartans.errors
  }
  allTartans.data.allTartansCsv.edges.forEach(
    ({ node, next, previous }) => {
      createPage({
        path: `/tartan/${node.fields.slug}`,
        component: path.resolve(`./src/templates/tartan.js`),
        context: {
          id: node.id,
          previous,
          next,
        },
      })
    }
  )
}

We decided to index tartans by letters and create paginated letter pages. These pages list tartans with links to their individual pages. We display a maximum of 60 tartans per page, and the number of pages per letter varies. For example, the letter “a” will have have four pages: tartans/a, tartans/a/2, tartans/a/3 and tartans/a/4. The highest number of pages (15) belongs to “m” due to a high number of traditional names starting with “Mac.”

The tartans/a/4 page should point to tartans/b as its next page and tartans/b should point to tartans/a/4 as its previous page.

We will run a for of loop through the letters array ["a", "b", ... , "z"] and query all tartans that start with a given letter. This can be done with filter and regex operator:

allTartansCsv(filter: { Name: { regex: "/^${letter}/i" } })

The previousLetterLastIndex variable will be updated at the end of each loop and store the number of pages per letter. The /tartans/b page need to know the number of a pages (4) since its previous link should be tartans/a/4.

// gatsby-node.js
const letters = "abcdefghijklmnopqrstuvwxyz".split("")
exports.createPages = async ({ graphql, actions }) => {
  const { createPage } = actions
  // etc.

  let previousLetterLastIndex = 1
  for (const letter of letters) {
    const allTartansByLetter = await graphql(`
      query {
        allTartansCsv(filter: {Name: {regex: "/^${letter}/i"}}) {
          nodes {
            Palette
            fields {
              slug
              Unique_Name
            }
          }
          totalCount
        }
      }
    `)
    if (allTartansByLetter.errors) {
      throw allTartansByLetter.errors
    }
    const nodes = allTartansByLetter.data.allTartansCsv.nodes
    const totalCountByLetter = allTartansByLetter.data.allTartansCsv.totalCount
    const paginatedNodes = paginateNodes(nodes, pageLength)
    paginatedNodes.forEach((group, index, groups) => {
      createPage({
        path:
          index > 0 ? `/tartans/${letter}/${index + 1}` : `/tartans/${letter}`,
        component: path.resolve(`./src/templates/tartans.js`),
        context: {
          group,
          index,
          last: index === groups.length - 1,
          pageCount: groups.length,
          letter,
          previousLetterLastIndex,
        },
      })
    })
    previousLetterLastIndex = Math.ceil(totalCountByLetter / pageLength)
  }
}

The paginateNode function returns an array where initial elements are grouped by pageLength

const paginateNodes = (array, pageLength) => {
  const result = Array()
  for (let i = 0; i < Math.ceil(array.length / pageLength); i++) {
    result.push(array.slice(i * pageLength, (i + 1) * pageLength))
  }
  return result
}

Now let’s look into the tartan template. Since Gatsby is a React application, we can use the components that we were building in the first part of this article.

// ./src/templates/tartan.js
import React from "react"
import { graphql } from "gatsby"
import Layout from "../components/layout"
import SvgTile from "../components/svgtile"
import SvgBg from "../components/svgbg"
import svgAsString from "../components/svgasstring"
import SvgDownloadLink from "../components/svgdownloadlink"
import PngDownloadLink from "../components/pngdownloadlink"

export const query = graphql`
  query($id: String!) {
    tartansCsv(id: { eq: $id }) {
      Palette
      Threadcount
      Origin_URL
      fields {
        slug
        Unique_Name
      }
    }
  }
`
const TartanTemplate = props => {
  const { fields, Palette, Threadcount } = props.data.tartansCsv
  const {slug} = fields
  const svg = SvgTile({
    palette: Palette,
    threadcount: Threadcount,
  })
  const svgData = svgAsString(svg)
  const svgSize = svg.props.width
  
  return (
    <Layout>
      <SvgBg svg={svg} />
      {/* title and navigation component comes here */}
      <div className="downloads">
        <SvgDownloadLink svgData={svgData} fileName={slug} />
        <PngDownloadLink svgData={svgData} size={svgSize} fileName={slug} />
      </div>
    </Layout>
  )
}
export default TartanTemplate

Finally let’s focus on the tartans index pages (the letter pages).

// ./src/templates/tartans.js
import React from "react"
import Layout from "../components/layout"
import {Link} from "gatsby"
import TartansNavigation from "../components/tartansnavigation"
const TartansTemplate = ({ pageContext }) => {
  const {
    group,
    index,
    last,
    pageCount,
    letter,
    previousLetterLastIndex,
  } = pageContext

  return (
    <Layout>
      <header>
        <h1>{letter}</h1>
      </header>
      <ul>
        {group.map(node => {
          return (
            <li key={node.fields.slug}>
              <Link to={`/tartan/${node.fields.slug}`}>
                <span>{node.fields.Unique_Name}</span>
              </Link>
            </li>
          )
        })}
      </ul>
      <TartansNavigation
        letter={letter}
        index={index}
        last={last}
        previousLetterLastIndex={previousLetterLastIndex}
      />
    </Layout>
  )
}
export default TartansTemplate

The TartansNavigation component adds next-previous navigation between the index pages.

// ./src/components/tartansnavigation.js
import React from "react"
import {Link} from "gatsby"

const letters = "abcdefghijklmnopqrstuvwxyz".split("")
const TartansNavigation = ({
  className,
  letter,
  index,
  last,
  previousLetterLastIndex,
}) => {
  const first = index === 0
  const letterIndex = letters.indexOf(letter)
  const previousLetter = letterIndex > 0 ? letters[letterIndex - 1] : ""
  const nextLetter =
    letterIndex < letters.length - 1 ? letters[letterIndex + 1] : ""
  
  let previousUrl = null, nextUrl = null

  // Check if previousUrl exists and create it
  if (index === 0 && previousLetter) {
    // First page of each new letter except "a"
    // If the previous letter had more than one page we need to attach the number 
    const linkFragment =
      previousLetterLastIndex === 1 ? "" : `/${previousLetterLastIndex}`
    previousUrl = `/tartans/${previousLetter}${linkFragment}`
  } else if (index === 1) {
    // The second page for a letter
    previousUrl = `/tartans/${letter}`
  } else if (index > 1) {
    // Third and beyond
    previousUrl = `/tartans/${letter}/${index}`
  }
  
  // Check if `nextUrl` exists and create it
  if (last && nextLetter) {
    // Last page of any letter except "z"
    nextUrl = `/tartans/${nextLetter}`
  } else if (!last) {
    nextUrl = `/tartans/${letter}/${(index + 2).toString()}`
  }

  return (
    <nav>
      {previousUrl && (
        <Link to={previousUrl} aria-label="Go to Previous Page" />
      )}
      {nextUrl && (
        <Link to={nextUrl} aria-label="Go to Next Page" />
      )}
    </nav>
  )
}
export default TartansNavigation

Final thoughts

Let’s stop here. I tried to cover all of the key aspects of this project. You can find all the tartanify.com code on GitHub. The structure of this article reflects my personal journey — understanding the specificity of tartans, translating them into SVG, automating the process, generating image versions, and discovering Gatsby to build a user-friendly website. It was maybe not as fun as our Scottish journey itself 😉, but I truly enjoyed it. Once again, a side project proved to be the best way to dig into new technology.

The post How We Created a Static Site That Generates Tartan Patterns in SVG appeared first on CSS-Tricks.

How I think about solving problems

Nicholas C. Zakas:

Eventually, I settled on a list of questions I would ask myself for each problem as it arose. I found that asking these questions, in order, helped me make the best decision possible:

1) Is this really a problem?
2) Does the problem need to be solved?
3) Does the problem need to be solved now?
4) Does the problem need to be solved by me?
5) Is there a simpler problem I can solve instead?

We've talked about what it takes to be a senior developer before, and I'd say this kind of thinking should be on that list as well.

Direct Link to ArticlePermalink

The post How I think about solving problems appeared first on CSS-Tricks.