If you have ever developed something for WordPress, be it a theme or a simple plugin, you are already familiar with the modularity of WordPress. WooCommerce is developed with extendability in mind also.
In this tutorial we will create a simple shipping method for WooCommerce which will calculate the cost of shipping. We will also add some restrictions to our plugin so that our shipping method is available only for certain countries.
To follow this tutorial you will need:
Before we begin, we will need to define how our shipping method will calculate the cost and where it can ship.
The cost will be determined by the weight we need to ship and by the zone where we need to ship. A zone is a number which is assigned to countries and to prices. The higher the number, the longer the shipping distance. Our fictional shipping company is shipping only to a few countries:
Our shipping company will be from Croatia, so Croatia is in zone 0. Let's define zones for the other countries:
Now that we have all the countries available for shipping with the corresponding zone, it's time to define prices.
I have mentioned also the weight, right? Our shipping company can ship up to 100 kg, and the prices are:
We have everything that we need to create our shipping method. Let's learn a little about the WooCommerce Shipping API.
When creating a shipping method, we need to extend the class from the WooCommerce abstract class WC_Shipping_Method
. Defined attributes in this class are:
$id
: ID (slug, keyword) of our shipping. Required.$number
: Integer ID.$method_title
: Name of our shipping shown in admin.$method_description
: Short description of our shipping shown in admin (Optional).$enabled
: String Boolean ("yes" or "no") that gives the information if our shipping is enabled and can be used or not.$title
: Used to display our shipping name on our site.$availability
: Defines if the shipping is available or not.$countries
: Array of countries this method is enabled for. Default value is an empty array.$tax_status
: Default value is taxable. If it is taxable then the tax will be charged.$fee
: Default value is 0. Fees for the method.$minimum_fee
: The minimum fee for the method. Default value is null.$has_settings
: Defines if this method has any settings. Default value is true.$supports
: Array containing features this method supports. Default value is an empty array.$rates
: Array of rates. This must be populated to register shipping costs. Default value is an empty array.Defined methods in the WC_Shipping_Method
are:
is_taxable()
: Returns whether or not we need to calculate tax on top of the shipping rate.add_rate( $args = array() )
: Pushes a shipping rate defined in the parameter $args into the attribute $rates
.has_settings()
: Returns the value of the attribute $has_settings
.is_available()
: Returns if the shipping is available. If there are countries set in the attribute $countries
and the attribute $availability
is set to values including, specific or excluding, it will return true or false if the country is available for shipping.get_title()
: Returns the title of this shipping.get_fee( $fee, $total )
: Returns the fee value for this shipping based on the parsed $fee
and $total
.supports( $feature )
: Returns if this shipping method is supporting a feature or not.Since the class WC_Shipping_Method
extends the class WC_Settings_API
, there are more attributes and methods that will not be explained here for the sake of simplicity.
There are also other methods that need to be defined so that the shipping can get or set settings and also calculate the actual cost of the shipping. These methods are:
init()
: Creates the form fields and settings (can be named differently, as long as we use the methods inside it and call it in the __constructor
method).calculate_shipping( $package )
: This is the method used to calculate the cost for this shipping. Package is an array
with the products to ship.In the calculate_shipping
method, we are adding the rate with the method add_rate
. This method accepts an array with several options:
id
: ID of the rate.label
: Label for the rate.cost
: Amount of the shipping. It can be a single value or an array
with costs for each item in the cart.taxes
: It accepts an array
of taxes or nothing so the tax is calculated by WooCommerce. It can even accept false
if you do not want the tax to be calculated.calc_tax
: Accepts per_order
or per_item
. If you use per_item
, an array
of costs will need to be provided.To register the shipping method, we need to add our shipping method in the array
of the registered method by passing the name of our class. We can get access to that array
and send the modified array
back using a WordPress filter that is defined inside the WooCommerce plugin. That filter is called woocommerce_shipping_methods
.
We will create our shipping method as a new plugin that extends the WooCommerce plugin. Create a new folder tutsplus-shipping under wp-content/plugins
. Also, create a file with the same name tutsplus-shipping.php
and add this code:
<?php /** * Plugin Name: TutsPlus Shipping * Plugin URI: http://code.tutsplus.com/tutorials/create-a-custom-shipping-method-for-woocommerce--cms-26098 * Description: Custom Shipping Method for WooCommerce * Version: 1.0.0 * Author: Igor Benić * Author URI: http://www.ibenic.com * License: GPL-3.0+ * License URI: http://www.gnu.org/licenses/gpl-3.0.html * Domain Path: /lang * Text Domain: tutsplus */ if ( ! defined( 'WPINC' ) ) { die; } /* * Check if WooCommerce is active */ if ( in_array( 'woocommerce/woocommerce.php', apply_filters( 'active_plugins', get_option( 'active_plugins' ) ) ) ) { function tutsplus_shipping_method() { if ( ! class_exists( 'TutsPlus_Shipping_Method' ) ) { class TutsPlus_Shipping_Method extends WC_Shipping_Method { /** * Constructor for your shipping class * * @access public * @return void */ public function __construct() { $this->id = 'tutsplus'; $this->method_title = __( 'TutsPlus Shipping', 'tutsplus' ); $this->method_description = __( 'Custom Shipping Method for TutsPlus', 'tutsplus' ); $this->init(); $this->enabled = isset( $this->settings['enabled'] ) ? $this->settings['enabled'] : 'yes'; $this->title = isset( $this->settings['title'] ) ? $this->settings['title'] : __( 'TutsPlus Shipping', 'tutsplus' ); } /** * Init your settings * * @access public * @return void */ function init() { // Load the settings API $this->init_form_fields(); $this->init_settings(); // Save settings in admin if you have any defined add_action( 'woocommerce_update_options_shipping_' . $this->id, array( $this, 'process_admin_options' ) ); } /** * Define settings field for this shipping * @return void */ function init_form_fields() { // We will add our settings here } /** * This function is used to calculate the shipping cost. Within this function we can check for weights, dimensions and other parameters. * * @access public * @param mixed $package * @return void */ public function calculate_shipping( $package ) { // We will add the cost, rate and logics in here } } } } add_action( 'woocommerce_shipping_init', 'tutsplus_shipping_method' ); function add_tutsplus_shipping_method( $methods ) { $methods[] = 'TutsPlus_Shipping_Method'; return $methods; } add_filter( 'woocommerce_shipping_methods', 'add_tutsplus_shipping_method' ); }
It may seem as if there is a lot to understand, but it is quite simple. First we check if the constant WPINC
is defined because if not, it means that someone is trying to access this file directly or from a location that is not WordPress.
Now that we are sure that this will be accessed from WordPress, we can move on. Before we start creating our shipping method for WooCommerce, we need to be sure that WooCommerce is active. We are checking if the file woocommerce.php
is in the array of active plugins that is saved in the database under the option active_plugins
.
We are then creating the function tutsplus_shipping_method
which we are also adding in the action woocommerce_shipping_init
. The action woocommerce_shipping_init
is the main action for WooCommerce Shippings which includes all the shipping classes before they get instantiated. By using that action we are sure that our shipping method will be included after WooCommerce has been initialised and in the right place for WooCommerce to use it.
The __construct
method of our class will set some general attributes. Some of them can be easily overwritten after the settings are loaded from the database in the method init
. Two other methods are left empty because we will define them later.
Our shipping method is available only in the previously determined list of countries. This will be set before the method init
inside the method __construct
. Add this in the method __construct
:
<?php //... $this->method_description = __( 'Custom Shipping Method for TutsPlus', 'tutsplus' ); // Availability & Countries $this->availability = 'including'; $this->countries = array( 'US', // Unites States of America 'CA', // Canada 'DE', // Germany 'GB', // United Kingdom 'IT', // Italy 'ES', // Spain 'HR' // Croatia ); $this->init(); //...
The attribute availability
is set to 'including'
so that this shipping is only available for the countries included in the attribute countries
. When WooCommerce wants to display the available shippings to our customer, it will check if the shipping country is included in the attribute countries
for this shipping.
If you look closely to our method __construct
, you can see that we are checking the settings for the enabled
and title
properties. We will create fields that will enable our properties to be changed.
Copy this code and populate our method init_form_fields
:
<?php function init_form_fields() { $this->form_fields = array( 'enabled' => array( 'title' => __( 'Enable', 'tutsplus' ), 'type' => 'checkbox', 'description' => __( 'Enable this shipping.', 'tutsplus' ), 'default' => 'yes' ), 'title' => array( 'title' => __( 'Title', 'tutsplus' ), 'type' => 'text', 'description' => __( 'Title to be display on site', 'tutsplus' ), 'default' => __( 'TutsPlus Shipping', 'tutsplus' ) ), ); }
Now you can go to WordPress administration and change those settings at WooCommerce > Settings > Shipping > TutsPlus Shipping.
Try changing the setting Enable and see on the tab Shipping Options if our shipping method is enabled or not.
We have also defined that our shipping method can ship up to 100 kg. What if that rule changes in the near future? We can easily allow that to be edited in the settings. We will add that setting so our method init_form_fields
looks like this now:
<?php function init_form_fields() { $this->form_fields = array( 'enabled' => array( 'title' => __( 'Enable', 'tutsplus' ), 'type' => 'checkbox', 'description' => __( 'Enable this shipping.', 'tutsplus' ), 'default' => 'yes' ), 'title' => array( 'title' => __( 'Title', 'tutsplus' ), 'type' => 'text', 'description' => __( 'Title to be display on site', 'tutsplus' ), 'default' => __( 'TutsPlus Shipping', 'tutsplus' ) ), 'weight' => array( 'title' => __( 'Weight (kg)', 'tutsplus' ), 'type' => 'number', 'description' => __( 'Maximum allowed weight', 'tutsplus' ), 'default' => 100 ), ); }
Now we can even set the maximum weight under the settings. We could make our countries, zones and everything else also customisable, but for the sake of simplicity we will skip that part.
With everything set now, we have one more step before we can use our shipping method when selling our products. We need to calculate the shipping cost based on the products in the visitor's cart.
We are going to update the method calculate_shipping
one step at a time so that you can understand each step. The first step is to get the cost by weight. Add this code to that method:
<?php //... public function calculate_shipping( $package ) { $weight = 0; $cost = 0; $country = $package["destination"]["country"]; foreach ( $package['contents'] as $item_id => $values ) { $_product = $values['data']; $weight = $weight + $_product->get_weight() * $values['quantity']; } $weight = wc_get_weight( $weight, 'kg' ); if( $weight <= 10 ) { $cost = 0; } elseif( $weight <= 30 ) { $cost = 5; } elseif( $weight <= 50 ) { $cost = 10; } else { $cost = 20; } } //...
We have defined a few starting variables: $weight
, $cost
, and $country
. The variable $weight
will hold the total weight from all the products, the variable $cost
will hold the cost of this shipping method, and the variable $country
will hold the ISO code for the selected shipping country.
We are getting the total weight by iterating the cart and adding the weight for each product in the cart to the variable $weight
. Once we have our total weight, we are using the function wc_get_weight
to convert the weight into kilograms since that is the unit in which our shipping method has set the limit.
The last thing here is to get the cost for the calculated weight. If you look closely at the last part, we did not set the limit on the 100 kg as we said. Our shipping cost will show the cost even for a cart with a total weight of 101 kg or more. This part of our shipping limits will be done later in the article as a restriction when processing checkout or updating the order.
Now that we have the cost based on the weight of the cart, we have to calculate the cost for the selected shipping country. Add this code next:
<?php //... public function calculate_shipping( $package ) { //... $countryZones = array( 'HR' => 0, 'US' => 3, 'GB' => 2, 'CA' => 3, 'ES' => 2, 'DE' => 1, 'IT' => 1 ); $zonePrices = array( 0 => 10, 1 => 30, 2 => 50, 3 => 70 ); $zoneFromCountry = $countryZones[ $country ]; $priceFromZone = $zonePrices[ $zoneFromCountry ]; $cost += $priceFromZone; } //...
The array $countryZones
holds the zones for each country. The second array $zonePrices
holds the prices for each zone. Once we have set both of those arrays, we get the cost by zone like this:
$countryZones
to get the zone.$zonePrices
to get the cost.$cost
.We calculated the cost by the total weight, and we have also added the cost by the shipping country. The last step here is to register the rate, so add this last part:
<?php //... public function calculate_shipping( $package ) { //... $rate = array( 'id' => $this->id, 'label' => $this->title, 'cost' => $cost ); $this->add_rate( $rate ); } //...
Here is the whole code for this method if you had trouble following it:
<?php //... public function calculate_shipping( $package ) { $weight = 0; $cost = 0; $country = $package["destination"]["country"]; foreach ( $package['contents'] as $item_id => $values ) { $_product = $values['data']; $weight = $weight + $_product->get_weight() * $values['quantity']; } $weight = wc_get_weight( $weight, 'kg' ); if( $weight <= 10 ) { $cost = 0; } elseif( $weight <= 30 ) { $cost = 5; } elseif( $weight <= 50 ) { $cost = 10; } else { $cost = 20; } $countryZones = array( 'HR' => 0, 'US' => 3, 'GB' => 2, 'CA' => 3, 'ES' => 2, 'DE' => 1, 'IT' => 1 ); $zonePrices = array( 0 => 10, 1 => 30, 2 => 50, 3 => 70 ); $zoneFromCountry = $countryZones[ $country ]; $priceFromZone = $zonePrices[ $zoneFromCountry ]; $cost += $priceFromZone; $rate = array( 'id' => $this->id, 'label' => $this->title, 'cost' => $cost ); $this->add_rate( $rate ); } //...
If you try now to view your cart or go to the checkout page and select a country that is available for this shipping, you'll get a shipping cost displayed with this custom shipping method. Here is a picture with a country from zone 3:
Since we have allowed the shipping method to register its rate even if the total weight of our cart is more than our limit, we have to add some restrictions. Our restriction will notify the customer that the order can't ship because of its weight.
In our function we will look for the shipping method which has been chosen. If the method is our TutsPlus_Shipping_Method
then we will check for its weight limit and the total weight in the cart. If the weight from the cart exceeds the weight limit, we will notify our customer.
After the filter woocommerce_shipping_methods
add this code:
<?php function tutsplus_validate_order( $posted ) { $packages = WC()->shipping->get_packages(); $chosen_methods = WC()->session->get( 'chosen_shipping_methods' ); if( is_array( $chosen_methods ) && in_array( 'tutsplus', $chosen_methods ) ) { foreach ( $packages as $i => $package ) { if ( $chosen_methods[ $i ] != "tutsplus" ) { continue; } $TutsPlus_Shipping_Method = new TutsPlus_Shipping_Method(); $weightLimit = (int) $TutsPlus_Shipping_Method->settings['weight']; $weight = 0; foreach ( $package['contents'] as $item_id => $values ) { $_product = $values['data']; $weight = $weight + $_product->get_weight() * $values['quantity']; } $weight = wc_get_weight( $weight, 'kg' ); if( $weight > $weightLimit ) { $message = sprintf( __( 'Sorry, %d kg exceeds the maximum weight of %d kg for %s', 'tutsplus' ), $weight, $weightLimit, $TutsPlus_Shipping_Method->title ); $messageType = "error"; if( ! wc_has_notice( $message, $messageType ) ) { wc_add_notice( $message, $messageType ); } } } } }
We are getting the packages which are separated by shipping. If all products are using the same shipping, it will return only one package with all the products. After that, we are getting the chosen methods, and then for each package we are checking if that package is shipped by our shipping method.
If the package is to be shipped with our shipping method, we are setting the weight limit from the settings, and after that we are calculating the total weight of our package. If the total weight exceeds our weight limit, it will notify the customer.
The order update happens each time the customer changes something on the checkout page. We will add the function tutsplus_validate_order
to the action woocommerce_review_order_before_cart_contents
. This action is called after everything has been set so that we can get the chosen shipping methods from session and the packages from shipping. Once the customer changes something, this action will trigger our function and add the notice if necessary.
Add this code after our function tutsplus_validate_order
:
<?php add_action( 'woocommerce_review_order_before_cart_contents', 'tutsplus_validate_order' , 10 );
When the customer clicks on the button to place the order or buy it, WooCommerce will process all the billing and shipping data alongside the cart contents and the chosen shipping.
If there are any WooCommerce error notices, it will stop the checkout process and display all those error notices to the customer. Since we have created a function that is using the session to get the chosen shipping methods, we have to add this function to an action that will be triggered after the session has been set. The action which will trigger just before WooCommerce checks if there is any error notice is woocommerce_after_checkout_validation
.
Let's add our function to that action:
<?php add_action( 'woocommerce_after_checkout_validation', 'tutsplus_validate_order' , 10 );
Here is the full code for this custom shipping method, so if you had any trouble following this tutorial, you can look here:
<?php /** * Plugin Name: TutsPlus Shipping * Plugin URI: http://code.tutsplus.com/tutorials/create-a-custom-shipping-method-for-woocommerce--cms-26098 * Description: Custom Shipping Method for WooCommerce * Version: 1.0.0 * Author: Igor Benić * Author URI: http://www.ibenic.com * License: GPL-3.0+ * License URI: http://www.gnu.org/licenses/gpl-3.0.html * Domain Path: /lang * Text Domain: tutsplus */ if ( ! defined( 'WPINC' ) ) { die; } /* * Check if WooCommerce is active */ if ( in_array( 'woocommerce/woocommerce.php', apply_filters( 'active_plugins', get_option( 'active_plugins' ) ) ) ) { function tutsplus_shipping_method() { if ( ! class_exists( 'TutsPlus_Shipping_Method' ) ) { class TutsPlus_Shipping_Method extends WC_Shipping_Method { /** * Constructor for your shipping class * * @access public * @return void */ public function __construct() { $this->id = 'tutsplus'; $this->method_title = __( 'TutsPlus Shipping', 'tutsplus' ); $this->method_description = __( 'Custom Shipping Method for TutsPlus', 'tutsplus' ); // Availability & Countries $this->availability = 'including'; $this->countries = array( 'US', // Unites States of America 'CA', // Canada 'DE', // Germany 'GB', // United Kingdom 'IT', // Italy 'ES', // Spain 'HR' // Croatia ); $this->init(); $this->enabled = isset( $this->settings['enabled'] ) ? $this->settings['enabled'] : 'yes'; $this->title = isset( $this->settings['title'] ) ? $this->settings['title'] : __( 'TutsPlus Shipping', 'tutsplus' ); } /** * Init your settings * * @access public * @return void */ function init() { // Load the settings API $this->init_form_fields(); $this->init_settings(); // Save settings in admin if you have any defined add_action( 'woocommerce_update_options_shipping_' . $this->id, array( $this, 'process_admin_options' ) ); } /** * Define settings field for this shipping * @return void */ function init_form_fields() { $this->form_fields = array( 'enabled' => array( 'title' => __( 'Enable', 'tutsplus' ), 'type' => 'checkbox', 'description' => __( 'Enable this shipping.', 'tutsplus' ), 'default' => 'yes' ), 'title' => array( 'title' => __( 'Title', 'tutsplus' ), 'type' => 'text', 'description' => __( 'Title to be display on site', 'tutsplus' ), 'default' => __( 'TutsPlus Shipping', 'tutsplus' ) ), 'weight' => array( 'title' => __( 'Weight (kg)', 'tutsplus' ), 'type' => 'number', 'description' => __( 'Maximum allowed weight', 'tutsplus' ), 'default' => 100 ), ); } /** * This function is used to calculate the shipping cost. Within this function we can check for weights, dimensions and other parameters. * * @access public * @param mixed $package * @return void */ public function calculate_shipping( $package ) { $weight = 0; $cost = 0; $country = $package["destination"]["country"]; foreach ( $package['contents'] as $item_id => $values ) { $_product = $values['data']; $weight = $weight + $_product->get_weight() * $values['quantity']; } $weight = wc_get_weight( $weight, 'kg' ); if( $weight <= 10 ) { $cost = 0; } elseif( $weight <= 30 ) { $cost = 5; } elseif( $weight <= 50 ) { $cost = 10; } else { $cost = 20; } $countryZones = array( 'HR' => 0, 'US' => 3, 'GB' => 2, 'CA' => 3, 'ES' => 2, 'DE' => 1, 'IT' => 1 ); $zonePrices = array( 0 => 10, 1 => 30, 2 => 50, 3 => 70 ); $zoneFromCountry = $countryZones[ $country ]; $priceFromZone = $zonePrices[ $zoneFromCountry ]; $cost += $priceFromZone; $rate = array( 'id' => $this->id, 'label' => $this->title, 'cost' => $cost ); $this->add_rate( $rate ); } } } } add_action( 'woocommerce_shipping_init', 'tutsplus_shipping_method' ); function add_tutsplus_shipping_method( $methods ) { $methods[] = 'TutsPlus_Shipping_Method'; return $methods; } add_filter( 'woocommerce_shipping_methods', 'add_tutsplus_shipping_method' ); function tutsplus_validate_order( $posted ) { $packages = WC()->shipping->get_packages(); $chosen_methods = WC()->session->get( 'chosen_shipping_methods' ); if( is_array( $chosen_methods ) && in_array( 'tutsplus', $chosen_methods ) ) { foreach ( $packages as $i => $package ) { if ( $chosen_methods[ $i ] != "tutsplus" ) { continue; } $TutsPlus_Shipping_Method = new TutsPlus_Shipping_Method(); $weightLimit = (int) $TutsPlus_Shipping_Method->settings['weight']; $weight = 0; foreach ( $package['contents'] as $item_id => $values ) { $_product = $values['data']; $weight = $weight + $_product->get_weight() * $values['quantity']; } $weight = wc_get_weight( $weight, 'kg' ); if( $weight > $weightLimit ) { $message = sprintf( __( 'Sorry, %d kg exceeds the maximum weight of %d kg for %s', 'tutsplus' ), $weight, $weightLimit, $TutsPlus_Shipping_Method->title ); $messageType = "error"; if( ! wc_has_notice( $message, $messageType ) ) { wc_add_notice( $message, $messageType ); } } } } } add_action( 'woocommerce_review_order_before_cart_contents', 'tutsplus_validate_order' , 10 ); add_action( 'woocommerce_after_checkout_validation', 'tutsplus_validate_order' , 10 ); }
The WooCommerce Shipping API enables you to create your own shipping method with simple steps. Limitations and availability can be set inside the shipping method when calculating the availability or the cost for the shipping method, but they can also be set outside the shipping method by using WooCommerce actions.
If you're looking for other utilities to help you build out your growing set of tools for WordPress or for code to study and become more well-versed in WordPress, don't forget to see what we have available in Envato Market.
If you have any questions about this or any other shipping method, you can post them in the comments below. You can also follow me on my blog or on twitter @igorbenic.
The Best Small Business Web Designs by DesignRush
/Create Modern Vue Apps Using Create-Vue and Vite
/Pros and Cons of Using WordPress
/How to Fix the “There Has Been a Critical Error in Your Website” Error in WordPress
/How To Fix The “There Has Been A Critical Error in Your Website” Error in WordPress
/How to Create a Privacy Policy Page in WordPress
/How Long Does It Take to Learn JavaScript?
/The Best Way to Deep Copy an Object in JavaScript
/Adding and Removing Elements From Arrays in JavaScript
/Create a JavaScript AJAX Post Request: With and Without jQuery
/5 Real-Life Uses for the JavaScript reduce() Method
/How to Enable or Disable a Button With JavaScript: jQuery vs. Vanilla
/How to Enable or Disable a Button With JavaScript: jQuery vs Vanilla
/Confirm Yes or No With JavaScript
/How to Change the URL in JavaScript: Redirecting
/15+ Best WordPress Twitter Widgets
/27 Best Tab and Accordion Widget Plugins for WordPress (Free & Premium)
/21 Best Tab and Accordion Widget Plugins for WordPress (Free & Premium)
/30 HTML Best Practices for Beginners
/31 Best WordPress Calendar Plugins and Widgets (With 5 Free Plugins)
/25 Ridiculously Impressive HTML5 Canvas Experiments
/How to Implement Email Verification for New Members
/How to Create a Simple Web-Based Chat Application
/30 Popular WordPress User Interface Elements
/Top 18 Best Practices for Writing Super Readable Code
/Best Affiliate WooCommerce Plugins Compared
/18 Best WordPress Star Rating Plugins
/10+ Best WordPress Twitter Widgets
/20+ Best WordPress Booking and Reservation Plugins
/Working With Tables in React: Part Two
/Best CSS Animations and Effects on CodeCanyon
/30 CSS Best Practices for Beginners
/How to Create a Custom WordPress Plugin From Scratch
/10 Best Responsive HTML5 Sliders for Images and Text… and 3 Free Options
/16 Best Tab and Accordion Widget Plugins for WordPress
/18 Best WordPress Membership Plugins and 5 Free Plugins
/25 Best WooCommerce Plugins for Products, Pricing, Payments and More
/10 Best WordPress Twitter Widgets
1 /12 Best Contact Form PHP Scripts for 2020
/20 Popular WordPress User Interface Elements
/10 Best WordPress Star Rating Plugins
/12 Best CSS Animations on CodeCanyon
/12 Best WordPress Booking and Reservation Plugins
/12 Elegant CSS Pricing Tables for Your Latest Web Project
/24 Best WordPress Form Plugins for 2020
/14 Best PHP Event Calendar and Booking Scripts
/Create a Blog for Each Category or Department in Your WooCommerce Store
/8 Best WordPress Booking and Reservation Plugins
/Best Exit Popups for WordPress Compared
/Best Exit Popups for WordPress Compared
/11 Best Tab & Accordion WordPress Widgets & Plugins
/12 Best Tab & Accordion WordPress Widgets & Plugins
1 /New Course: Practical React Fundamentals
/Preview Our New Course on Angular Material
/Build Your Own CAPTCHA and Contact Form in PHP
/Object-Oriented PHP With Classes and Objects
/Best Practices for ARIA Implementation
/Accessible Apps: Barriers to Access and Getting Started With Accessibility
/Dramatically Speed Up Your React Front-End App Using Lazy Loading
/15 Best Modern JavaScript Admin Templates for React, Angular, and Vue.js
/15 Best Modern JavaScript Admin Templates for React, Angular and Vue.js
/19 Best JavaScript Admin Templates for React, Angular, and Vue.js
/New Course: Build an App With JavaScript and the MEAN Stack
/Hands-on With ARIA: Accessibility Recipes for Web Apps
/10 Best WordPress Facebook Widgets
13 /Hands-on With ARIA: Accessibility for eCommerce
/New eBooks Available for Subscribers
/Hands-on With ARIA: Homepage Elements and Standard Navigation
/Site Accessibility: Getting Started With ARIA
/How Secure Are Your JavaScript Open-Source Dependencies?
/New Course: Secure Your WordPress Site With SSL
/Testing Components in React Using Jest and Enzyme
/Testing Components in React Using Jest: The Basics
/15 Best PHP Event Calendar and Booking Scripts
/Create Interactive Gradient Animations Using Granim.js
/How to Build Complex, Large-Scale Vue.js Apps With Vuex
1 /Examples of Dependency Injection in PHP With Symfony Components
/Set Up Routing in PHP Applications Using the Symfony Routing Component
1 /A Beginner’s Guide to Regular Expressions in JavaScript
/Introduction to Popmotion: Custom Animation Scrubber
/Introduction to Popmotion: Pointers and Physics
/New Course: Connect to a Database With Laravel’s Eloquent ORM
/How to Create a Custom Settings Panel in WooCommerce
/Building the DOM faster: speculative parsing, async, defer and preload
1 /20 Useful PHP Scripts Available on CodeCanyon
3 /How to Find and Fix Poor Page Load Times With Raygun
/Introduction to the Stimulus Framework
/Single-Page React Applications With the React-Router and React-Transition-Group Modules
12 Best Contact Form PHP Scripts
1 /Getting Started With the Mojs Animation Library: The ShapeSwirl and Stagger Modules
/Getting Started With the Mojs Animation Library: The Shape Module
/Getting Started With the Mojs Animation Library: The HTML Module
/Project Management Considerations for Your WordPress Project
/8 Things That Make Jest the Best React Testing Framework
/Creating an Image Editor Using CamanJS: Layers, Blend Modes, and Events
/New Short Course: Code a Front-End App With GraphQL and React
/Creating an Image Editor Using CamanJS: Applying Basic Filters
/Creating an Image Editor Using CamanJS: Creating Custom Filters and Blend Modes
/Modern Web Scraping With BeautifulSoup and Selenium
/Challenge: Create a To-Do List in React
1 /Deploy PHP Web Applications Using Laravel Forge
/Getting Started With the Mojs Animation Library: The Burst Module
/10 Things Men Can Do to Support Women in Tech
/A Gentle Introduction to Higher-Order Components in React: Best Practices
/Challenge: Build a React Component
/A Gentle Introduction to HOC in React: Learn by Example
/A Gentle Introduction to Higher-Order Components in React
/Creating Pretty Popup Messages Using SweetAlert2
/Creating Stylish and Responsive Progress Bars Using ProgressBar.js
/18 Best Contact Form PHP Scripts for 2022
/How to Make a Real-Time Sports Application Using Node.js
/Creating a Blogging App Using Angular & MongoDB: Delete Post
/Set Up an OAuth2 Server Using Passport in Laravel
/Creating a Blogging App Using Angular & MongoDB: Edit Post
/Creating a Blogging App Using Angular & MongoDB: Add Post
/Introduction to Mocking in Python
/Creating a Blogging App Using Angular & MongoDB: Show Post
/Creating a Blogging App Using Angular & MongoDB: Home
/Creating a Blogging App Using Angular & MongoDB: Login
/Creating Your First Angular App: Implement Routing
/Persisted WordPress Admin Notices: Part 4
/Creating Your First Angular App: Components, Part 2
/Persisted WordPress Admin Notices: Part 3
/Creating Your First Angular App: Components, Part 1
/How Laravel Broadcasting Works
/Persisted WordPress Admin Notices: Part 2
/Create Your First Angular App: Storing and Accessing Data
/Persisted WordPress Admin Notices: Part 1
/Error and Performance Monitoring for Web & Mobile Apps Using Raygun
/Using Luxon for Date and Time in JavaScript
7 /How to Create an Audio Oscillator With the Web Audio API
/How to Cache Using Redis in Django Applications
/20 Essential WordPress Utilities to Manage Your Site
/Introduction to API Calls With React and Axios
/Beginner’s Guide to Angular 4: HTTP
/Rapid Web Deployment for Laravel With GitHub, Linode, and RunCloud.io
/Beginners Guide to Angular 4: Routing
/Beginner’s Guide to Angular 4: Services
/Beginner’s Guide to Angular 4: Components
/Creating a Drop-Down Menu for Mobile Pages
/Introduction to Forms in Angular 4: Writing Custom Form Validators
/10 Best WordPress Booking & Reservation Plugins
/Getting Started With Redux: Connecting Redux With React
/Getting Started With Redux: Learn by Example
/Getting Started With Redux: Why Redux?
/Understanding Recursion With JavaScript
/How to Auto Update WordPress Salts
/How to Download Files in Python
/Eloquent Mutators and Accessors in Laravel
1 /10 Best HTML5 Sliders for Images and Text
/Site Authentication in Node.js: User Signup
/Creating a Task Manager App Using Ionic: Part 2
/Creating a Task Manager App Using Ionic: Part 1
/Introduction to Forms in Angular 4: Reactive Forms
/Introduction to Forms in Angular 4: Template-Driven Forms
/24 Essential WordPress Utilities to Manage Your Site
/25 Essential WordPress Utilities to Manage Your Site
/Get Rid of Bugs Quickly Using BugReplay
1 /Manipulating HTML5 Canvas Using Konva: Part 1, Getting Started
/10 Must-See Easy Digital Downloads Extensions for Your WordPress Site
/22 Best WordPress Booking and Reservation Plugins
/Understanding ExpressJS Routing
/15 Best WordPress Star Rating Plugins
/Creating Your First Angular App: Basics
/Inheritance and Extending Objects With JavaScript
/Introduction to the CSS Grid Layout With Examples
1Performant Animations Using KUTE.js: Part 5, Easing Functions and Attributes
Performant Animations Using KUTE.js: Part 4, Animating Text
/Performant Animations Using KUTE.js: Part 3, Animating SVG
/New Course: Code a Quiz App With Vue.js
/Performant Animations Using KUTE.js: Part 2, Animating CSS Properties
Performant Animations Using KUTE.js: Part 1, Getting Started
/10 Best Responsive HTML5 Sliders for Images and Text (Plus 3 Free Options)
/Single-Page Applications With ngRoute and ngAnimate in AngularJS
/Deferring Tasks in Laravel Using Queues
/Site Authentication in Node.js: User Signup and Login
/Working With Tables in React, Part Two
/Working With Tables in React, Part One
/How to Set Up a Scalable, E-Commerce-Ready WordPress Site Using ClusterCS
/New Course on WordPress Conditional Tags
/TypeScript for Beginners, Part 5: Generics
/Building With Vue.js 2 and Firebase
6 /Best Unique Bootstrap JavaScript Plugins
/Essential JavaScript Libraries and Frameworks You Should Know About
/Vue.js Crash Course: Create a Simple Blog Using Vue.js
/Build a React App With a Laravel RESTful Back End: Part 1, Laravel 5.5 API
/API Authentication With Node.js
/Beginner’s Guide to Angular: Routing
/Beginners Guide to Angular: Routing
/Beginner’s Guide to Angular: Services
/Beginner’s Guide to Angular: Components
/How to Create a Custom Authentication Guard in Laravel
/Learn Computer Science With JavaScript: Part 3, Loops
/Build Web Applications Using Node.js
/Learn Computer Science With JavaScript: Part 4, Functions
/Learn Computer Science With JavaScript: Part 2, Conditionals
/Create Interactive Charts Using Plotly.js, Part 5: Pie and Gauge Charts
/Create Interactive Charts Using Plotly.js, Part 4: Bubble and Dot Charts
Create Interactive Charts Using Plotly.js, Part 3: Bar Charts
/Awesome JavaScript Libraries and Frameworks You Should Know About
/Create Interactive Charts Using Plotly.js, Part 2: Line Charts
/Bulk Import a CSV File Into MongoDB Using Mongoose With Node.js
/Build a To-Do API With Node, Express, and MongoDB
/Getting Started With End-to-End Testing in Angular Using Protractor
/TypeScript for Beginners, Part 4: Classes
/Object-Oriented Programming With JavaScript
/10 Best Affiliate WooCommerce Plugins Compared
/Stateful vs. Stateless Functional Components in React
/Make Your JavaScript Code Robust With Flow
/Build a To-Do API With Node and Restify
/Testing Components in Angular Using Jasmine: Part 2, Services
/Testing Components in Angular Using Jasmine: Part 1
/Creating a Blogging App Using React, Part 6: Tags
/React Crash Course for Beginners, Part 3
/React Crash Course for Beginners, Part 2
/React Crash Course for Beginners, Part 1
/Set Up a React Environment, Part 4
1 /Set Up a React Environment, Part 3
/New Course: Get Started With Phoenix
/Set Up a React Environment, Part 2
/Set Up a React Environment, Part 1
/Command Line Basics and Useful Tricks With the Terminal
/How to Create a Real-Time Feed Using Phoenix and React
/Build a React App With a Laravel Back End: Part 2, React
/Build a React App With a Laravel RESTful Back End: Part 1, Laravel 9 API
/Creating a Blogging App Using React, Part 5: Profile Page
/Pagination in CodeIgniter: The Complete Guide
/JavaScript-Based Animations Using Anime.js, Part 4: Callbacks, Easings, and SVG
/JavaScript-Based Animations Using Anime.js, Part 3: Values, Timeline, and Playback
/Learn to Code With JavaScript: Part 1, The Basics
/10 Elegant CSS Pricing Tables for Your Latest Web Project
/Getting Started With the Flux Architecture in React
/Getting Started With Matter.js: The Composites and Composite Modules
Getting Started With Matter.js: The Engine and World Modules
/10 More Popular HTML5 Projects for You to Use and Study
/Understand the Basics of Laravel Middleware
/Iterating Fast With Django & Heroku
/Creating a Blogging App Using React, Part 4: Update & Delete Posts
/Creating a jQuery Plugin for Long Shadow Design
/How to Register & Use Laravel Service Providers
2 /Unit Testing in React: Shallow vs. Static Testing
/Creating a Blogging App Using React, Part 3: Add & Display Post
/Creating a Blogging App Using React, Part 2: User Sign-Up
20 /Creating a Blogging App Using React, Part 1: User Sign-In
/Creating a Grocery List Manager Using Angular, Part 2: Managing Items
/9 Elegant CSS Pricing Tables for Your Latest Web Project
/Dynamic Page Templates in WordPress, Part 3
/Angular vs. React: 7 Key Features Compared
/Creating a Grocery List Manager Using Angular, Part 1: Add & Display Items
New eBooks Available for Subscribers in June 2017
/Create Interactive Charts Using Plotly.js, Part 1: Getting Started
/The 5 Best IDEs for WordPress Development (And Why)
/33 Popular WordPress User Interface Elements
/New Course: How to Hack Your Own App
/How to Install Yii on Windows or a Mac
/What Is a JavaScript Operator?
/How to Register and Use Laravel Service Providers
/
waly Good blog post. I absolutely love this…