Wordpress Notes

References

Best Options for developers

  • Select s theme. Generate one for you: https://underscores.me/
  • Observe the best elements from web and customize and merge with yours.
  • Use Gutenberg block editor for page ??

Notes on s theme

  • index.php is used as template file when more specific template (e.g. home.php for home page) does not exist.

Psueudo code for theme index.php

index.php() of theme:

   get_header($name = null); ==>  wordpress API.
     * Renders <html> and <head> areas;
     * defined in wp-includes/general-template.php
     * Can specify header name e.g. 'home', 'blog', etc to customize.
     * Calls do_action('get_header', $name) to trigger action, if any.
     * Calls locate_template( array('header-home.php', ..., 'header.php'))

     #primary div .content-area
        #main main .site-main      // Uses <main> tag.
          header 

            h1 .page-title
               single_post_title() if applicable.

            Diplay Posts specific to post type using:
               template-parts/content-<post_type>.php

               <article>  #post-id  .post-classes ... </article>
                 <header>    .entry-header
                   <div>     .entry-content
                   <footer>  .entry-footer        

            Display the_posts_navigation();    // wordpress function.
               # Display controls for: Older Posts; Newer Posts, etc

     get_sidebar($name = null) :      // wordpress function

        do_action() - Trigger actions on 'get_sidebar' event.
        Use template from : sidebar-$name.php, ..., sidebar.php

     get_footer($name = null) :

Layout for twenty* themes

<html class='no-js'>   # modernizr / other scripts replaces the no-js to js.
                       # This enables use of 2 css classes depending on js supported or not.
                       # e.g. .js body { ... }  .no-js body { ... }
  <head>
    <script> which replaces class=no-js to js. This flags css that js is active. </script>
    lot of junk meta
    jquery ...
  </head>

  # Many themes like genesis use body classes heavily to layout the contents using css ...
  <body class="home page-template-default page page-id-13 logged-in admin-bar no-customize-support 
        twentyseventeen-front-page has-header-image page-two-column colors-light">

    <div id="page" class="site">
      <header id="masthead" class="site-header" role="banner">
        <div class="custom-header">
          <div class="custom-header-media">
            <div id="wp-custom-header" class="wp-custom-header"><img src="header.jpg" ... /></div> 
          </div>

         <div class="site-branding">
          <div class="wrap">
             <div class="site-branding-text">
                    <h1 class="site-title"><a href="http://wp.local/" rel="home">Wordpress Reference Virgin Site</a></h1>

                    <p class="site-description">Just another WordPress site</p>
              </div><!-- .site-branding-text -->
          </div><!-- .wrap -->
         </div><!-- .site-branding -->
        </div><!-- .custom-header -->
      </header><!-- #masthead -->

      <div class="site-content-contain">

        <div id="content" class="site-content">
          <div id="primary" class="content-area">
            <main id="main" class="site-main" role="main">
              // Since we do not have page specific templates, the 'static page' is formatted like any other single post ???
              <article id="post-13" class="twentyseventeen-panel  post-13 page type-page status-publish hentry" >
                <div class="panel-content">
                  <div class="wrap">
                    <header class="entry-header">
                      <h2 class="entry-title">My Arbitrary Home Page</h2>
                        <span class="edit-link">.. <span class="screen-reader-text"> "My Arbitrary Home Page"</span></a></span>
                    </header><!-- .entry-header -->
                    <div class="entry-content">
                        <p>This is arbitrary home page with arbitrary contents.</p>
                    </div><!-- .entry-content -->
                </div><!-- .wrap -->
              </article><!-- #post-## -->
            </main><!-- #main -->
          </div><!-- #primary -->
        </div><!-- #content -->

        <footer id="colophon" class="site-footer" role="contentinfo">
          <div class="wrap">
            <div class="site-info">
                    <a href="https://wordpress.org/" class="imprint"> Proudly powered by WordPress    </a>
            </div><!-- .site-info -->
          </div><!-- .wrap -->
        </footer><!-- #colophon -->
      </div><!-- .site-content-contain -->
    </div><!-- #page -->
  </body>
</html>

Nice ascii character symbols

raquo »laquo «rsaquo ›lsaquo ‹rdquo ”ldquo “rsquo ’lsquo ‘
raquo - Right (double) arrow quote; rsaquo - single. etc.

is_front_page() vs is_home() vs is_page() vs is_single() vs themename_is_frontpage()

Home vs Front Page

  • By default Home Page = Front Page = Your Latest (10) Posts.

  • is_home() page is always associated with 'Your Latest Posts'

  • Settings => Readings : Provides option to set your Home page as either static page or latest posts.

  • If home page is static page, (it is usually named as 'Home'), you have option of naming your posts page (usually named as Blog)

  • is_home() returns true for static page -- only if it is set to view the Blog Posts Index. Returns false otherwise.

  • is_front_page() returns true in more cases -- when viewing the Site Front Page (whether displaying the blog posts index or a static page)

  • Home is a misnomer since it returns false on static page which does not display the 'posts'.

  • Front Page term is more consistent since it is true for static page, but also considers 'Front page of all posts'.

  • You can simply use:

    if($_SERVER['REQUEST_URI'] == '/') {
      // you must be on the home page
    }
    
  • when is_front_page() and is_home() conditions, both are true, the template front-page.php will be used instead of home.php.

  • is_page() is true for posts page. Also is_page('About') is true if the page title or slug is 'About'.

  • is_single() is true only if it is single post. False for multiple posts page or other static pages.

  • is_single( array( 7, 5, 'The Jedi', 'the-sith' ) ) would return true for posts with the ID of 7 or 5 or a post with the title "The Jedi" or the slug "the-sith".

  • Also See: has_nav_menu('top')

  • Also See: get_template_part('template_parts/header/header', 'image'); To include header-image.php

  • If your Custom Front Page does not have header menu for other pages, visitors will be stuck at home.

Common CSS

.rtl {}
.home {}
.blog {}
.archive {}
.date {}
.search {}
.paged {}
.attachment {}
.error404 {}
.single postid-(id) {}
.attachmentid-(id) {}
.attachment-(mime-type) {}
.author {}
.author-(user_nicename) {}
.category {}
.category-(slug) {}
.tag {}
.tag-(slug) {}
.page-parent {}
.page-child parent-pageid-(id) {}
.page-template page-template-(template file name) {}
.search-results {}
.search-no-results {}
.logged-in {}
.paged-(page number) {}
.single-paged-(page number) {}
.page-paged-(page number) {}
.category-paged-(page number) {}
.tag-paged-(page number) {}
.date-paged-(page number) {}
.author-paged-(page number) {}
.search-paged-(page number) {}

User Work Flow

  • Create A Dummy Page as 'My Arbitrary Front Static Home Page'
  • Create Another Dummy Page as 'My Blog'
  • Create New Categories such as 'Music', 'Technology', 'Movies'
  • Settings => Readings => Set Static Home Page; Set Home Page => 'My Static Home Page'; Posts Page => 'My Blog'
  • Appearance => Menus => Create Menu : 'My Top Menu' : Enable Auto Add Option to link to all top level pages. If you want finer control, only link the top level pages that you want to this menu. Display Location: Top Menu. (The set of Display/Menu Locations Available is limited as per theme)
  • Appearance => Menus => Create Menu : 'My Custom Resources Menu' ; Attach one Page, One Custom Link, One Category as menu items to this menu. Push and drag one menu item to be child of another menu item to create 'sub menu' hierarchy.
  • A Menu can appear in multiple places.
  • Every Location (e.g. Top, Social Icons) can be attached to atmost single Menu only.
  • Every Page / Post / Custom Link / Category can be attached to any number of single menus.
  • There is no predefined Top Level Menu; There is only predefined location: Top ; You can choose to attach any menu there. Usually a menu that is set to 'auto add' all top level pages. // ??? If you want conditional top level menu, do not attach any menu to 'Top Position'
  • A menu is not necessarily Navigation Menu. It can be just a pull down to select/filter posts among various categories for example.

Conditional Menu

  • If you want conditional top level menu, different menu for different pages, Use 'Conditional Menu' Plugin. e.g. https://themify.me/conditional-menus

  • You can copy hader.php from parent theme to your own child theme and edit as follows :

    <?php if ( is_page('projects') )
            wp_nav_menu( array( 'theme_location' => 'primary', 'menu' => 'conditional-menu-name', 'menu_class' => 'nav-menu' ) );
          else
            wp_nav_menu( array( 'theme_location' => 'primary', 'menu' => 'Primary', 'menu_class' => 'nav-menu' ) );
    
    // The changes will be lost if you change the theme, though. Locations / Menu classes are theme specific.
    
  • You can use custom page template for each page.

Page Templates

  • A page template can be applied to a single page, a page section, or a class of pages.

  • Specific Page templates overrides generic ones. For example, a page template named page-about.php overrides page.php or index.php

  • If a page template has a template name, WordPress users editing the page can choose the template.

  • For example, you can build page templates for:

    • full-width, one-column
    • two-column with a sidebar on the right
    • two-column with a sidebar on the left
    • three-column
  • Some advanced themes support 12 columns grid and many packed page templates to choose from.

  • Template hierarchy from specific to generic: Page Custom Assigned Template >> page-{slug}.php >> page-{id}.php >> page.php >> singular.php { single post } >> index.php

  • For one-time custom template, copy page.php to page-{slug}.php in wp-content/themes/your-theme/ directory. Wordpress will find it automatically for you.

  • Reusable page templates live in top level dir of theme or within page-templates/ dir. The comments contents indicate this as 'Template' (but it is not a required convention technically) :

    <?php /* Template Name: Example Template */ ?>
    <?php
      /**
          Template Name: Full Width Page
          @package WordPress
          @subpackage Twenty_Fourteen
          @since Twenty Fourteen 1.0
       */
    
  • You can use code something like :

    if ( is_page_template( 'page-templates/my-template.php' ) ) {
         include_once 'page-templates/my-template.php';
    }
    

Template Parts

More reusable code can be organized inside template-parts/ subdir :

get_template_part(‘content’)                  =>  Load content.php. 
get_template_part(‘header’ ,‘widgets’)        =>  load header-widgets.php else header.php

Example :

// From index.php of twentyseventeen theme ...
while ( have_posts() ) : 
    the_post();                  // Sets current page type is 'post' ??
    get_template_part( 'content', get_post_format() );   // Post formats: aside, excerpt, video, audio, none, link, etc.
endwhile;

template-parts/post/content-excert.php :

<article>
 <header class='entry-header'> 
   <div class='entry-summary'> ... </div>
 </header>
</article>

Theme Level Options

Certain theme level options must not be confused as page level or post level. For example :

if ( 'one-column' === get_theme_mod( 'page_layout' )  )  ...

Above means 'Theme level modified value' of page_layout sets how all pages must be formatted by default. It is implemented as a wrapper over get_option() framework. All theme options of one theme are stored in single db column.

Some other theme level parametes are : colorscheme, panel*, page_options. (All these are theme specific)

Wordpress core theme level supported features

The add_theme_support( 'custom-logo', array('height' => 100, ..)) enables wp core support for custom logo. Likely core values include 'post-formats', 'post-thumbnails', 'html5', 'custom-logo', 'custom-header-uploads', 'custom-header', 'custom-background', 'title-tag', 'starter-content', etc. Using clean css is much easier.

The html5 theme support is really good. The markup is more cleaner with <section> kind of tags. The form looks cleaner with better options. Browser offline cache hints improve performance. Displaying 'Responsive' page is much easier (without javascripts). Only disadvantage could be that not all old browsers support all HTML5 features.

Child Theme

Consists of :

  • A folder with following files:
  • functions.php
  • style.css file.

The comment in style.css is what defines the parent theme !!! It is weird but true !!! :

/*
Theme Name:   Twenty Eleven Child
Description:  Child theme for the Twenty Eleven design
...
Template:    twentyeleven                  <== This defines parent theme !!!
Version:    0.1
*/
  • The functions.php is loaded after parent one. By default parent templates will be used.

  • For importing parent css you can either use @import url("../twentyeleven/style.css"); or enque style function in functions.php file. Otherwise parent style is not included.

  • For adding template in child theme, all you have to do is to insert proper comment :

    <?php
    /*
     * Template Name: Page for my custom purpose
     */
    # Save this file as template-my-custom-page.php 
    

WHEN TO USE A CHILD THEME

For small css changes use :

  • custom CSS plugin
  • Jetpack and SiteOrigin CSS

For larger changes and template changes, use child theme.

Create functions.php

Remember wordpress is based on some kind of event framework. Some wordpress built-in events and you can add your own events ... You need to know about all well known events ...

add_action( 'wp_enqueue_scripts', 'enqueue_parent_styles' );

//  add_action( $hook, $function_to_add, $priority, $accepted_args ); priority 1-999; 1-highest priority;
//                                                  $accepted_args : used rarely when multiple args accepted for hooks

function enqueue_parent_styles() {

   // Enable both parent style and this style ...
   wp_enqueue_style( 'parent-style', get_template_directory_uri().'/style.css' );

}

You can have 2 types of hooks: actions and filters:

  • The actions do not have input data.
  • Filters have input data that you should return optionally after modifying it anyway you want.

For documentation, see:

Search the WordPress core code for apply_filters( ‘filter_name’, ...) and do_action(...) to locate.

Another alternative approach for styling is to do (like child theme wizard does ) :

function theme_enqueue_styles() {
    wp_enqueue_style('parent-style', get_template_directory_uri() . '/style.css');
    wp_enqueue_style('child-style', get_stylesheet_directory_uri() . '/style.css',
                      array($parent_style)); // parent style is dependency.

}
add_action('wp_enqueue_scripts', 'theme_enqueue_styles');

Child Theme Considerations

After child theme migration all widget instances (option widget<name>) and sidebar widget association info (option sidebars_widgets) exist in database. But they won't be visible unless the page templates in new/child theme refer to them.

Every page/post is associated with page template :

$template = get_post_meta( $post->ID, '_wp_page_template', true )

wp post meta list 2

  +---------+--------------------------+-------------------------------------------+
  | post_id | meta_key                 | meta_value                                |
  +---------+--------------------------+-------------------------------------------+
  | 2       | _wp_page_template        | default                                   |
  | 2       | spacious_page_layout     | default_layout                            |
  | 2       | _elementor_edit_mode     | builder                                   |
  | ....        ....     .....         | .....                                     |
  +---------+--------------------------+-------------------------------------------+

After switching to child theme, you need to watch these:

wp db search spacious-cfg1

wp_options:option_name   601:theme_mods_spacious-cfg1-child

wp option get theme_mods_spacious-cfg1-child

  array (
    'nav_menu_locations' => array ( 'primary' => 2, 'footer' => 3,),
    'sidebars_widgets'   => ... )
  • wp_head, wp_footer
  • the_content e.g. add_filter( 'the_content', 'shortcode_unautop' )

Customizing your own menu

You can register you own new class of menu then use Appearance => Edit menus to put items inside that menu. The 'footer-menu' is not alread predefined here :

function register_footer_menu() {
    register_nav_menu('footer-menu', __('Footer Menu'));
}
add_action('init', 'register_footer_menu');

Note: Typical footer.php starts with </div> to terminate the section div started from get_header() called from header.php

Producing clean html code

You should better remove all traces from html code that it was produced from word press. Things like <meta name="generator" content="wordpress xxxx.xxx"> should go.

Put code in functions.php file to remove all these junk.

Or simply install some header clean plugin. e.g. https://wordpress.org/plugins/wp-hide-security-enhancer/

Debug Site

define('WP_DEBUG', true);
define('WP_DEBUG_LOG', true);
define('WP_DEBUG_DISPLAY', true);
/* Check debug.log in wp-content dir */

define('WP_DEBUG_SCRIPT', true); // Rarely used. Needed only if you change core php, js files.

// To debug db ...
define( 'SAVEQUERIES', true )    // All db queries are cached; Use with: var_dump($wpdb->queries)

global $wpdb;
error_log( print_r( $wpdb->queries, true ) );

With in functions.php, you can call :

error_log( print_r( $variable, true ) );
var_dump( $variable_to_test );
<script> console.log (...); </script>

error_log( get_class( $obj ) );

error_log( print_r( $GLOBALS, true ) );

Writing Plugin

Writing plugin involves mainly using following wordpress API :

add_option($name, $value, $deprecated, $autoload);
// Creates a new option; does nothing if option already exists.
get_option($option);
update_option($option_name, $newvalue);

Using extract function

// Watch out!!! Security Risk.

$arr = array(
    'red' => 5
);
extract($arr);
echo $red; // 5

Plugin to add custom template

reddit recommendations

Usually you should look for following qualities in theme:

  • Amount of theme options for topography i.e. layout.
  • Support for other page builders like Elementor.
  • Header customization like Transparent header.
  • Amount of Page templates. (like. Contact, About pages)
  • Amount of free site templates to import.
  • Typography customization as theme option like font size, color changes.
  • Speed - should not be bloated.

Templates

Best Free simple templates:

  • Astra - Backed by company, Clean code, Supports all page builders.
    • 85 stars, 14 contributors. Intelligent layout.
    • Simpler options, good enough varieties of templates. Focused on speed.
    • Based on underscore S theme !!!
    • Poor documentation.
  • oceanwp. Most Free Templates and customizable. Supports all page builders:
    • git hub https://github.com/oceanwp/oceanwp 125 stars. 8 contributors. active.
    • using it's own custom css not based on any specific framework like bootstrap.
    • Responsive support is very good.
    • Most users use page builder or elementor. Pro version costs $120! expensive.
  • Generate press is great lightweight theme. (Do not like Advt to go for GP premium) 119 stars. 4 contributors. Experienced developer but very conservative to support all page builders. Mobile first. Easy to design responsive.
  • s underscores is lightwieght and truly open source;
  • Frontier - simple and good.
  • spacious - This is a free theme created by ThemeGrill:
    • It also offer famous free ColorMag magazine theme.
  • Hueman : 498 Stars! 19 contributors ! Backed by single person Nikeo :
    • Awesome typography and layout features.
    • Best example for how to define header. Big header but hides itself while scrolling down, small header appears while scrolling up !!
    • Comes with Nimble visual builder -- quite good.
    • See: https://demo-hueman.presscustomizr.com/demo/typography/

Best premium themes

  • Sahifa - Responsive WordPress News / Magazine / Blog Theme Supports lot of shortcodes (i.e. small code which generates complex html code)
  • Enfold - Multi purpose generic e-commerce best selling By Kreisty. Based on 12 columns grid, generated by less. Now a days out of fashion.
  • Be - Comes with lot of examples.
  • ?? Genesis by StudioPress is great parent theme to be customized by child. ??? (commercial, guttenberg ready)
  • Elementor plugin for drag and drop page editing.
  • For measuring speed: I have 20-25 plugins and my site scores 90 on PageSpeed and loads in about 1.5-2 seconds on GTmetrix.
  • I have used Plugin Organizer to block unnecessary plugins; See https://wordpress.org/plugins/plugin-organizer/
  • Page builder by site origin

My Selected Theme

  • Spacious - Requires css: div.header-post-title-container { display: none; }

Best Visual Composer

  • Elementor.
  • Beaver Builder.
  • Divi Builder.
  • Thrive Architect.
  • SiteOrigin Page Builder.
  • WPBakery Page Builder.
  • Themify Builder.
  • Brizy.
  • Gutenberg uses block design
  • Live composer https://livecomposerplugin.com
  • jetpack - From wordpress. custom css functionality (visual editor) is most useful.
  • gutenberg - Visual code editor

My Plugins

  • Akismet - Anti spam (default)
  • Yoast SEO
  • Title Remover
  • Page Builder
  • Plugin Organizer
  • Autoptimize - Remove emoji cruft, etc
  • Insert Headers and Footers - CSS Styles across Themes - Best Option (But not page specific!!!)
  • header-and-footer-scripts - This is page specific !! Great.

Caching

Use comet cache to speed up; To remove comet cache:

Log into your site via FTP; perhaps using FileZilla.
Delete this file: /wp-content/advanced-cache.php
Delete this directory: /wp-content/plugins/comet-cache/
Remove this line from your /wp-config.php file: define('WP_CACHE', TRUE);
Comet Cache is now completely uninstalled and you can start fresh

wp cli

install wp

curl -O https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar
sudo cp wp-cli.phar  /usr/local/bin/wp
sudo chmod 755    /usr/local/bin/wp

wp user list
wp user update 1 --user_pass=$UP3RstrongP4$$w0rd ; 1 is for admin.

wp theme install ../my-theme.zip  --activate

Synopsis

wp command subcommand requiredparam --optionalparam --optionalparam2=value

Install fresh copy

wp core download

wp core config --dbname=mydbname --dbuser=mydbuser --dbpass=mydbpass --dbhost=localhost --dbprefix=whebfubwef_ --extra-php <<PHP
define( 'WP_DEBUG', true );
define( 'WP_DEBUG_LOG', true );
PHP

wp db create
wp core install --url=http://siteurl.com --title=SiteTitle --admin_user=username --admin_password=mypassword --admin_email=my@email.com

# Reinstall / upgrade without default themes and plugins:
wp core download --skip-content --force

Change site url

wp option get home 
wp option get siteurl
wp option get category-base
wp option get tag-base
wp option get permalink_structure

wp option update home 'http://example.com'
wp option update siteurl 'http://example.com'

To clone site

- Copy restore the database to new name. (Use mysqldump and mysql)
- sed -i 's/old-text/new-text/g' old.db.sql > new.db.sql;  OR ...
- wp search-replace http://oldname.com  http://newname.com   # This does string replace on all tables in db. especially wp_options table.

suppress servername warning

echo "ServerName localhost" | sudo tee /etc/apache2/conf-available/servername.conf sudo a2enconf servername

Extra commands

wp plugin list
wp plugin install advanced-custom-fields jetpack ninja-forms myplugin.zip so-css --activate
wp plugin search searchterm
wp plugin update wordpress-seo     # Upgrades to latest version
wp search-replace oldstring newstring --dry-run
wp db import file.sql
wp db export file.sql
wp user generate --count=10 --role=author
wp term generate --count=12  # An example category is a term.
wp post generate --count=50

wp post list             # Lists post ids.
wp post meta list <id>   # All meta info about post.

$ wp option add my_option foobar
Success: Added 'my_option' option.

$ wp option update my_option '{"foo": "bar"}' --format=json
Success: Updated 'my_option' option.

# Delete option.
$ wp option delete my_option

# Cleanup spam comments.
wp comment delete $(wp comment list --status=spam --format=ids)

# Keep users. Clean everything in db.
wp db reset

wp menu list

+---------+-------------------+-------------------+-----------+-------+
| term_id | name              | slug              | locations | count |
+---------+-------------------+-------------------+-----------+-------+
| 3       | Social Links Menu | social-links-menu | footer    | 5     |
| 2       | Top Menu          | top-menu          | primary   | 5     |
+---------+-------------------+-------------------+-----------+-------+

wp menu item list  top-menu
+-------+-----------+-------------+-----------------------------------+----------+
| db_id | type      | title       | link                              | position |
+-------+-----------+-------------+-----------------------------------+----------+
| 18    | custom    | Home        | http://blogfree.local/            | 1        |
| 19    | post_type | Blog        | http://blogfree.local/blog        | 2        |
| 40    | post_type | Best Of Web | http://blogfree.local/best-of-web | 3        |
| ...   | ......... | ........... | ................................. | .        |
+-------+-----------+-------------+-----------------------------------+----------+

wp menu item list  social-links-menu
+-------+--------+-----------+--------------------------------------------------+----------+
| db_id | type   | title     | link                                             | position |
+-------+--------+-----------+--------------------------------------------------+----------+
| 21    | custom | Yelp      | https://www.yelp.com                             | 1        |
| 22    | custom | Facebook  | https://www.facebook.com/wordpress               | 2        |
+-------+--------+-----------+--------------------------------------------------+----------+

wp menu item add-custom social-links-menu Blogger http://thavamuni.blogger.com  # This menu item is now added.

wp menu location assign <menu> <location>     # Location is sidebar name. e.g. primary, footer
wp menu location remove <menu> <location>
wp menu location list [--format=<format>]
+----------+--------------+
| location | description  |
+----------+--------------+
| primary  | Primary Menu |
| footer   | Footer Menu  |
+----------+--------------+
wp menu location remove  social-links-menu footer

wp menu create <menu-name> [--porcelain]        # porcelain just prints menu id.
wp menu create 'Zatvia Services' --porcelain    # The slug zatvia-services is created.
35

wp menu item add-custom zatvia-services  'Web Services' http://zatvia.com/web-services 
wp menu item delete <db-id> 

Managing Posts

# Create post and schedule for future
$ wp post create --post_type=page --post_title='A future post' --post_status=future --post_date='2020-12-01 07:00:00'
Success: Created post 1921.

# Create post with content from given file
$ wp post create ./post-content.txt --post_category=201,345 --post_title='Post from file'
Success: Created post 1922.

# Create a post with multiple meta values.
$ wp post create --post_title='A post' --post_content='Just a small post.' --meta_input='{"key1":"value1","key2":"value2"}
Success: Created post 1923.

# Delete post skipping trash
$ wp post delete 123 --force
Success: Deleted post 123.

# Delete all pages
$ wp post delete $(wp post list --post_type='page' --format=ids)
Success: Trashed post 1164.
Success: Trashed post 1186.

# Delete all posts in the trash
$ wp post delete $(wp post list --post_status=trash --format=ids)
Success: Deleted post 1268.
Success: Deleted post 1294.

# Attach the imported media as 'featured image' for all posts.
wp post list --post_type=post --format=ids | xargs -0 -d ' ' -I %
                           wp post meta add % _thumbnail_id <thumbnail-id>

Posts kinds

grep register_post_type reveals :

./wp-includes/post.php: register_post_type( 'post', array(
./wp-includes/post.php: register_post_type( 'page', array(
./wp-includes/post.php: register_post_type( 'attachment', array(
./wp-includes/post.php: register_post_type( 'revision', array(
./wp-includes/post.php: register_post_type( 'nav_menu_item', array(
./wp-includes/post.php: register_post_type( 'custom_css', array(
./wp-includes/post.php: register_post_type( 'customize_changeset', array(
./wp-includes/post.php: register_post_type( 'oembed_cache', array(
./wp-includes/post.php: register_post_type( 'user_request', array(
  • A page is a post.

  • A post entry is a post.

  • An attachment media is a separate post.

  • Even a navigation menu item is a post.

  • You can list them with filter. e.g. wp post_type list :

    +---------------------+-----------------------+-------------+--------------+--------+---------------------+
    | name                | label                 | description | hierarchical | public | capability_type     |
    +---------------------+-----------------------+-------------+--------------+--------+---------------------+
    | post                | Posts                 |             |              | 1      | post                |
    | page                | Pages                 |             | 1            | 1      | page                |
    | attachment          | Media                 |             |              | 1      | post                |
    | revision            | Revisions             |             |              |        | post                |
    | nav_menu_item       | Navigation Menu Items |             |              |        | post                |
    | custom_css          | Custom CSS            |             |              |        | post                |
    | customize_changeset | Changesets            |             |              |        | customize_changeset |
    | oembed_cache        | oEmbed Responses      |             |              |        | post                |
    | user_request        | User Requests         |             |              |        | post                |
    | acf-field-group     | Field Groups          |             | 1            |        | post                |
    | acf-field           | Fields                |             | 1            |        | post                |
    +---------------------+-----------------------+-------------+--------------+--------+---------------------+
    
  • E.g. You can support a new post type as "book" with title, author, etc as attributes with also support for additional custom fields when you call register_post_type(...., supports => (..., 'custom-fields', ...)).

  • Following css classes are added for post automatically by wordpress by calling post_class() by theme:

    .post-id
    .post
    .attachment
    .sticky
    .hentry (hAtom microformat pages)
    .category-ID
    .category-name
    .tag-name
    .format-{format-name}
    .type-{post-type-name}
    .has-post-thumbnail
    

Wordpress DB Cleanup SQL queries

php version switching

sudo update-alternatives --set php /usr/bin/php7.0
sudo a2dismod php7.0
sudo a2enmod php7.1
sudo systemctl restart apache2

sudo apt install software-properties-common
sudo add-apt-repository ppa:ondrej/php
sudo apt-get update
sudo apt install php5.6   [PHP 5.6] # Never use 5.5 and earlier.
sudo apt install php7.0   [PHP 7.0]
sudo apt install php7.1   [PHP 7.1]

dynamic sidebar

Synopsis:

<?php if ( is_active_sidebar( 'left-sidebar' ) ) : ?>  // True if sidebar contains atleast 1 widget.
  <ul id="sidebar">
       <?php dynamic_sidebar( 'left-sidebar' ); ?>
  </ul>
<?php endif; ?>

dynamic_sidebar('top_menu');  // Not necessarily used for sidebars. All locations.

// You register sidebar and define items there. These will be displayed later.
register_sidebar( array(
 'id'          => 'top-menu',
 'name'        => __( 'Top Menu', $text_domain ),      // __() used for translation. text_domain = 'default'
 'description' => __( 'This sidebar is located above the age logo.', $text_domain ),
) );

Inspiration

Wordpress github themes

Wordpress Free themes

CSS / JS Templates / Resources

Good Websites

Foundation Site

  • Zurb Foundation is complete framework.
  • npm install -g foundation-cli
  • foundation new # Creates empty project.

Youtube Reviews

  • Element plugin can be used to edit the pieces which are already created. Customers may want this feature to make minor edits.

Tyler Moore

  • Without using specific supported "Page Template", you can not remove the sidebar.
  • You need site origin plugin page builder for ... and widgets for adding map on your page, This is useful to change layout of pages to 3 or 4 columns in a row. The 'rows' support 'Full Width' property. Very useful for Mobile First pages. Every row support background image/color, etc.
  • Black video Tiny MCE plugin. This acts like widget. We will insert this MCE editor for each box in the layout as "widget".
  • Easy google fonts plugin
  • Title Remover plugin
  • Contact Form 7?
  • Spacer Plugin To control spacing. It becomes an item in Tiny MCE Editor.
  • LightBox Plus Colorbox - If you want to play video within popup box.
  • http://unsplash.com free great images.
  • http://logomakr.com for creating logo.
  • Customize => Typography => Theme Typography is really useful to preview different fonts live. If your theme supports, all your <span class='myname'> ... </span> will be available to edit here in 'Theme Typography'.
  • Wordpress Image Admin Editor can be used to crop images!!
  • For 2018, use Elementor builder instead of SiteOrigin page builder and oceanwp , ocean extra?
  • Elementor is really handy to view mobile view and adjust styles specific to mobile!!! It internally generates media specific css underneath.
  • Elementor templates can be used as 'page' template or 'section' template. They are in .json format.
  • OceanWP even supports page specific 'Header Style' !!! Lot of control.
  • Phlox is another good theme.

Responsive Design

  • For large screen limit the width because long line (> 80 chars) is difficult to read :

    @media (min-width: 700px) {
        .weather-forecast {
          width: 700px;
        }
    }
    
  • For small screens, do not add any margin at all. Use full width: .div.fullWidth { width: 100%; }

  • Use media queries to use different stylesheet, or in same css.

Theme Reviews

Bones - Wordpress - Rejected

  • Bones Free wordpress theme, Mobile First, minimal with SASS support, https://themble.com/bones/
  • Currently not active, no support.
  • An archive is available here: git@github.com:a-santarosa/eddiemachado-bones-8440c49.git (6 years old) :
    • Adds support for sidebar, comments, etc. Uses HTML5 tags like viewport meta, header, nav,
    • Uses classes like clearfix, wrap, eightcol, ninecol, etc.
    • Every post is proceeded by 300px image thumbnail.
    • footer contains <nav> and footer links.
    • index.php displays all posts. (default behaviour when home page is not pointing to static another page)
    • Empty style.css !!!

Skeleton - Non-Wordpress

Verdict: Great basic responsive theme.

  • Skeleton is a simple, responsive boilerplate to kickstart any responsive project.

  • Layout :

    | Skeleton/
    ├── index.html
    ├── css/
    │   ├── normalize.min.css
    │   └── skeleton.css           // Just 400 lines!
    └── images/
        └── favicon.ico
    
  • The grid is a 12-column fluid grid with a max width of 960px.

  • Uses classes like "four columns", "eleven.columns", etc.

  • The typography base is Raleway served by Google. Great choice.

LMS Plugins - For online courses

Learning Management Systems Plugins ...

  • Best Free: Learnpress - with paid options also.
  • Other Paid options: LearnDash, LifterLMS, WP Courseware, etc.

Site Testing Profiling Tools

  • GTMetrix
  • Pingdom ? webpagetest.org
  • Google test for mobile responsiveness ?? with UI to select different mobile layouts with URLs.
  • Use of non-blocking asynchronous font and site loading. Some wordpress plugins like 'Lazy loading' enables websites for this.
  • Analyze page contents percentage of images and number of requests.

Asynchrnous loading techniques

  • If you are loading Google Fonts in the <head> via css then it is render-blocking file.

  • Web Font Loader — a joint project between Google and Adobe Typekit. Any browser that supports @font-face can use this.

  • Any css is render blocker. Use javascript to set font preference later :

    <script src="https://ajax.googleapis.com/ajax/libs/webfont/1.5.18/webfont.js"></script>
    <script>
     WebFont.load({
        google: {
          families: ['Source Sans Pro:400,600,700,400italic,700italic', 'Roboto Condensed:400,700']
        }
      });
    </script>
    
  • Font Awesome, the popular icon font, provides async codes.

  • TypeKit's embed codes

  • Autoptimize plugin for WordPress combines css, etc.

  • Google analytics kind of javascripts can be performance killers. Should be deferred until initial page load.

  • Alternatives must be put inside <noscript> tags.

Best Menu Builders

  • WP Mega Menu plugin helps. (both free and paid)
  • Max Mega Menu is completely free. Converts regular menu to mega menu and customize:
    • better to add 0.5 sec delay before displaying menu on hover.
    • if you need multiple mega menus, max mega menu supports multiple menu locations with different settings for each location.
    • You can use widgets in your mega menus like maps, contact form, etc.
  • Premium options include Uber Menu, Slick Menu, etc.

Logo Fonts and colors

  • Merienda
  • Pacifico
  • Kaushan Script
  • Permanent Marker
  • Courgette
  • Rock Salt
  • Quick Sand
  • Arima Madurai — Regular
  • Nunito
  • Muli
  • Comfortaa - Round comfortable font.
  • Aladin

In wordpress, custom css do one of these :

@import url('https://fonts.googleapis.com/css?family=Courgette|Pacifico');

<style>
@import url('https://fonts.googleapis.com/css?family=Courgette|Pacifico');
</style>

.site-title a {
    font-family: 'gloria hallelujah', cursive;
    font-size: 5rem;
    font-weight: 300;
    color: #009900;
    text-shadow: 2px 1px 1px #d7d7d7; 
}

For image manipulation:

convert input.png -trim output.png    # Trims borders of same color.
convert 2868cif.jpg -fuzz 10% -transparent white 2868cif.png    # convert white to transparent 

Good Colors

  • lightteal: #028CB9;
  • darkteal: #064F68; rgb(2, 140, 185)
  • thinteal: #9FD2E7;

Markdown, Syntax Highlighting options

Use of Markdown for pages

Verdict:

There is no ready made solution. Use pandoc to convert between .md and .html (both ways). Maintain the post capabilities using elementor and various widgets.

If you want to use markdown in posts/pages directly, it won't be efficient to translate on the fly. If you really want it... then use:

  • WP editor.md best one:
    • Requires table of contents plus plugin for [toc] support.
    • Supports mindmap.
  • Jp markdown
  • wp markdown

Syntax Highlighting

  • Code Prettify: Just use javascript to highlight any <pre> and <code> contents: https://github.com/kasparsd/code-prettify
  • Prismatic: Gives 3 options Prism.js (famous), Highlight.js, plain (for custom css) https://wordpress.org/plugins/prismatic/ Also escapes html when necessary.
  • An extremely popular one is google-code-prettify. To syntax highlight a block, you put class="prettyprint" on either the code or pre tag. It's a larger file size than Prism, but one advantage is that it auto-detects language

Using Prism Javascript

<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/prism/1.5.0/themes/prism.min.css">

<script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.5.0/prism.min.js"></script>

<pre><code class="language-css">  ...  </code></pre>    // languge-python etc.

Widgets Implementation

// =========================================================================
// You invoke the fixed instances of the widgets in functions.php
// register_sidebar() invokes core widget class Sidebar instances.

register_sidebar(name = 'Left Sidebar',     // Right Sidebar, Header Sidebar ...
                                            // Business Middle Left Sidebar, 
                                            // Footer Sidebar 3, ...
                 id = spacious_right_sidebar | ....   
                 description, before/after widget and title what html piece should appear);

// This id is used in css for styling.
// This id is used in templates to get html pieces before/after to insert.
// =========================================================================
// 
// Custom widget definitions are registered like below. 
// inc/widgets/spacios_service_widget :
//
//        class spacious_testimonial_widget extends WP_Widget {   ... }
//

register_widget('spacious_service_widget') ; // Also: Featured single page, Call to action, Testimonial, Recent work.  

The widget definition (i.e. class constructor) specifies following:

    css class = widget_testimonial       // example.
    Name  = TG: Testimonial              // And Description.
    width and height;  e.g.  200, 250

The widget invocation is done by calling Classname::widget() function ....

    Following instance specific attributes supported for widget: title, text, name, AND any number of custom attributes!!!
    Print widget contents; e.g. echo $before widget . "<div> something... </div>" . $title . ... echo $after_widget ; 

============================================================================================================================

Note: wp option get sidebars_widgets   # Lists my sidebar definitions and associated widget instances.

      I can not have a 'sidebar' which is not defined as part of theme install.
      All sidebars are defined in widgets.php (during theme setup only).
      dynamic_sidebar('sidebar-1' or ID)  renders all associated widgets in that sidebar as mentioned in register_sidebar()
                              The customization options allow the add/delete widgets in these predefined list of sidebars.

      A plugin can easily add more widgets by defining more widget classes:
         - A widget is a block of reusable html code with predefined contents that can be modified.

      A plugin can easily define more sidebar names *and* associated widgets, but it is useful only if :
         - The page template uses the same sidebar definition and places them accordingly. (middle, top, bottom, whatever).
         - There is customizer support to add/delete widgets from sidebars.
         - Elementor can 'recognize' sidebars in the page and can support add/delete widgets.

      Wordpress comes with 12 default widgets: Text, Calendar, 'Recent Posts', 'Archives' etc.
      Spacious adds only 5 widgets focused for business: Testimonial, Recent Work, Services, Featured, Call-To-Action.

============================================================================================================================

Who invokes custom widgets ?

1. From functions.php - spacious_setup() run only once after theme install :

     $starter_content defines following:
         'widgets'        : array( areas and list(widget_class, args)) 
         'posts'          : home (uses business.php template), about, blog, contact (uses contact.php). 
         'attachments'    : Image logo,
         'options'        : Static front page named 'home' and page for posts is blog; More sensible default.
                            // 'show_on_front'  => 'page';  'page_on_front'  => '{{home}}'; 'page_for_posts' => '{{blog}}'

                              wp option get page_for_posts      #   23
                              wp post get 23
                              +-----------------------+------------------------------+
                              | Field                 | Value                        |
                              +-----------------------+------------------------------+
                              | ID                    | 23                           |
                              | post_title            | Blog                         |
                              | post_name             | blog                         |
                              | guid                  | http://thava.net/?page_id=23 |
                              | post_type             | page                         |
                              +-----------------------+------------------------------+

          'theme_mods'    : Theme modifications options. Mainly spacious[option_name]=value entries.
                            wp option get spacious; Lists all these options.
                            many options disabled later. e.g. spacious_activate_slider1

          'nav_menus'     : Defines (location, menu) mappings. e.g. 'primary' => Primary Menu with home, blog, about, contact items.
                                                                    'footer'  => Footer  Menu with home, blog, about, contact items.

          add_theme_support($starter_content);   // If theme does not call this wordpress core starter content alone is used.

      add_action( 'after_setup_theme', 'spacious_setup' );

2. Static initialization from functions.php;         // 
3. Page template - When page is rendered using page template.


Where widget instance data is stored ?

Usually, every widget class can have only one entry in wp_options table. All instances data must be stored in that single entry.
e.g. widget_text, widget_search. The data is usually stored in json format.
For example, widget_text represents : (Title, text) combo;  wp option get widget_text ; Lists around 20 text instances.

Wordpress Internals

A Sidebar is a theme feature introduced with Version 2.2. It's basicaly a vertical column provided by a theme for displaying information other than the main content of the web page. Themes usually provide at least one sidebar at the left or right of the content. Sidebars usually contain widgets that an administrator of the site can customize.

Theme may implement sidebar using:

  • page templates or
  • register_sidebar() and dynamic_sidebar()
  • Using both.

register_sidebar() examples:

register_sidebar( ..., 'Left Sidebar', ... )
register_sidebar( ..., 'Right Sidebar', ... )
register_sidebar( ..., 'Business Topbar', ... )
register_sidebar( ..., 'Contact sidebar', ... )

Sidebar includes widgets. Widget examples :

register_widget( 'spacious_service_widget' );
// Class spacious_service_widget must be defined.
// It has widget() function to render the widget.
// It has update() function to set attributes.
//        If update() returns new instance array, it supports multi-instance.
  • Each widget instance attributes are stored under 'widget_<widget_name>' option :

    $ wp option get widget_text     # widget_search, widget_archives, etc.
    
    array( 2 => array ( 'title' => 'Find Us', ... ),   // 2nd instance ...
           3 => ....,
           _multi_widget => 1 )                        // This widget supports multi instance.
    
  • There is "Menu Locations" define by register_nav_menus(); There are sidebar locations defined by register_sidebar(); It is left to theme to implement more abstractions for "Supported Location Areas". i.e. It may support abstract "Primary" and "Secondary" Menu locations. The secondary location may really be left/right/footer location.

  • No widget details are stored in DB until some sidebar decides to include one or more instances of widgets. See below for more details.

How to pre-populate widgets insidebar

To activate the widgets get/set "sidebars_widgets" option :

$ wp option get sidebars_widgets

array (
   ...

            'spacious_left_sidebar' =>
           array (
             0 => 'text-13',
             1 => 'text-21',
             2 => 'search-4',
             3 => 'text-18',
           ), ...
 )
  • For each sidebar name, the list of widgets appear in that order. The search-4 means the 4th instance of the "search" widget, etc.

I suggest writing it directly into the database with get_option('sidebars_widgets') which should give an array, and save it with update_option('sidebars_widgets', $new_activated_widgets)

get_sidebar vs dynamic_sidebar

  • Typically Page Template --includes--> Sidebar Template(get_sidebar()) --includes--> dynamic_sidebar()
  • The get_sidebar( $slug ) template tag includes the sidebar-$slug.php template-part file.
  • The dynamic_sidebar( $slug ) template tag outputs the $slug dynamic sidebar, as defined by register_sidebar( array( 'id' => $slug ) )
  • get_sidebar(templatename) is for loading a sidebar-template of the name 'sidebar-templatename.php', which would have dynamic_sidebar(sidebarname) in it. If you don't need the template, you can place dynamic_sidebar directly in your theme or other area. Beware, get_sidebar contains hooks that won't get called if it isn't used

Compare Widget Plugins

---------------------------------------------------------------------------------
                        Elementor                   SiteOrigin
---------------------------------------------------------------------------------
Editing Modes           Visual Editor               Back-end editor and lightweight live editor
Inline Editing          Yes                         No
Free Widgets            28                          26
Responsive Previews     Yes                         Yes
Show/hide by device     Yes                         Kind of, with CSS
Free Page Templates     38+                         26+
Save own templates?     Yes                         No, but can easily clone
Code lock-in?           No, leaves clean HTML       Some widgets leave behind shortcodes

Amazing capabilities for Elementor. You can create your own page templates !!! Elementor editing, Advanced Option, Hide Widgets selectively on desktop, tablet and mobile !!!

Elementor supports global widgets which is using same 'widget instance' in different pages. When you edit the definition in one page, all other pages also it becomes active.

Elementor uses terminology: Sections, Columns; Also supports reusable piece of code as blocks. Site origin supports: Rows, columns.

Site Origin Free allows directly entering custom css for row/columns, where as elementor only allows entering css id and class. You must enter custom css in global place. (This may be a good thing since you have single place to control all your custom editing).

Elementor Pro allows entering custom css within same window of visual editor.

Custom Sidebars and Widgets

A sidebar is really not defined by location, but defined by some arbitrary 'condition' that can be used anywhere in the page. The condition could be 'Am I in Header?', 'Left' ..etc. Or it could be 'Is current page == 'Home' ?' or anything arbitrary.

There are plugins which support that:

  • WooSidebars (FREE) (Also widgetlogic)

  • Widget Logic ... gives better examples :

    EXAMPLES
    is_home() — just the main blog page
    !is_page('about') — everywhere EXCEPT this specific WP ‘page’
    !is_user_logged_in() — shown when a user is not logged in
    is_category(array(5,9,10,11)) — category page of one of the given category IDs
    is_single() && in_category('baked-goods') — single post that’s in the category with this slug
    current_user_can('level_10') — admin only widget
    strpos($_SERVER['HTTP_REFERER'], "google.com")!=false — widget to show when clicked through from a google search
    is_category() && in_array($cat, get_term_children( 5, 'category')) — category page that’s a descendent of category 5
    global $post; return (in_array(77,get_post_ancestors($post))); — WP page that is a child of page 77
    global $post; return (is_page('home') || ($post->post_parent=="13"));
    
  • Dropdown menu widget is promising: https://wordpress.org/plugins/dropdown-menu-widget/

Plugin Internals

Activation, Deactivation, Uninstall hooks

register_activation_hook( __FILE__, 'my_plugin_activation' );
function my_plugin_activation() {
  add_option( 'my_plugin_activated', time() );
}

Spacious Theme Notes

Page Template              Layout Support                         Comments

Default Template           Left, Right(Default),                  Wordpress built-in
                           No sidebar Full Width,
                           No sidebar Centered.   
  • Pagebuilder Template ignores Layout types left, right, full-width, etc. It always has only header and footer.
  • Spacious comes with only 3 templates: business.php contact.php page-builder.php All other things are built-in templates. E.g. About page uses: built-in page.php

Chrome Tips

Delete url redirect cache

Go to chrome://net-internals pulldown top right menu tools then clear cache to clear 301 redirects to old sites, if any.

Comparison Of Page Templates

Spacious Page Templates

  • Business : Everything in sidebars and middle bars. No content. Can not be reused.
  • Page builder template : Allows content to be edited ...

Notes: Footer is global and fixed. If you want conditional footer content, you should insert conditional widgets.

Twenty themes Page Templates

Features:

  • No page templates to choose from
  • Page Order (a number) can be specified in 'Page Attributes' Box.
  • Custom fileds can be created for page. (can be used in theme).
  • Using screen options, you can say if page should be 1 column or 2 columns.

Elementor Page Templates

Once you start edit the page using elementor, you must use elementor editor only. Normal editor updates do not reflect in classic editor. But elementor editor updates reflect in classic editor without additional css tagging. So you do not have full control over styling - you get only what elementor gives you. In that aspect Tiny MCE editor gives you full control over styling.

Astra Page Templates

Supports single default template but have support for 'Astra Settings' for :

  • Sidebar location: left/right/disable
  • Title Enable/Disable
  • Header/Footer Enable/Disable
  • Based on s theme and grid layout

Oceanwp Templates

  • Supports default template plus 'Landing Page' template.
  • What is more useful is Oceanwp Settings in 'Page New' options:
    • Sidebar - Left/Right/None/Both
    • Title Enable/Disable
    • Customize Title and Subheading
  • Header/Footer Enable/Disable
  • Deadly Feature: For header/footer you can select your own template created in Theme Panel/My Library
  • Enable breadcrumbs
  • Using different navigation menu for different pages.
  • Large/Medium/Small breakpoints for this page. e.g. Desktop: if width > 1020 the page will display with only max width 1020.
  • Page specific logo and retina logo.
  • shortcodes to enter at the top/bottom new header/footer, etc. If you define your own custom shortcodes, it is handy.
  • Great documentation: https://docs.oceanwp.org/

ThemeIsle Hestia Template

  • Supports 1) wordpress built-in default template and following tempates:

    template-fullwidth.php      template-pagebuilder-full-width.php
    template-pagebuilder-blank.php  template-page-sidebar.php
    
  • Clean implementation for page builder blank support. Header calls just wp_head() and footer just calls wp_footer(); We are free to insert whatever we want in content including header navigation bars.

Generate Press

  • There is only one page template, but very good custmization optins (like Astra)
  • Everything customized by native wordpress customization screens
  • Recommends code snippets plugin.
  • Recommends Pluginception plugin to create your own plugin to put all your stuff in single plugin.

Plugins to Add custom Page Templates

Tip: https://wordpress.org/plugins/themeisle-companion orbit fox plugin is useful
to add more one click import templates.

Tip: If you want to add your own shortcode: https://generatewp.com/shortcodes/

Compare CSS Styles of Themes

Elementor

  • The buttons as clickable menu is implemented as anchor tags <a> with role=button attribue.

  • The img tag uses srcset attribute :

    <img alt="my awesome image" src="banner.jpeg"
         srcset="banner-HD.jpeg 2x, banner-phone.jpeg 640w, banner-phone-HD.jpeg 640w 2x">
    
     The above would serve banner-phone.jpeg to devices with viewport width under 640px, 
     banner-phone-HD.jpeg to small screen high DPI devices, banner-HD.jpeg to high DPI devices 
     with screens greater than 640px, and banner.jpeg to eve;rything else.
    
     There are also other methods like CSS media queries you can use to produce the same effect.
    

Free Images Resources

Pixeden
Graphicsfuel
Pickaface
Unsplash
Uifaces
pexals.com
pixabay
lifeofpix
picjumbo
jaymantri
https://www.reddit.com/r/web_design/comments/3klvqv/what_are_your_best_places_for_commercial_free/

https://www.toptal.com/designers/subtlepatterns/

Custom Fields

ACF plugin hides screen metabox for custom fields. Add this to your functions.php to get this back :

add_filter( 'acf/settings/remove_wp_meta_box', '__return_false' );

When you add a custom field for a post, you add it with "meta-key" and "meta-value". By default, after each post, all meta data (e.g. author, date, etc) are displayed using the_meta() call. This also displays your key:value. For example, you add a meta key, "my_post_class" = "width200". This will result it:

<?php the_meta(); ?>

It might look like this in the source code:

   <ul class='post-meta'>
   ....
   <li><span class='post-meta-key'>author:</span> thava </li>
   <li><span class='post-meta-key'>my_post_class:</span> width200 </li>
   ....
   </ul>
# You don't want that. You can change the post template to add the post class using your field
# Or add a filter function for default post class to add your classes to post class.

Tip:

get_post_meta requires a third parameter, "false" returns the Array (default), 
"true" returns only the first result (NOT as an array).

You can use the post_class filter to add more classes if you prefer that way.

<div class="posts">
<?php if ( have_posts() ) : while ( have_posts() ) : the_post(); ?>
   <div <?php post_class(); ?>>
      <?php the_content(); ?>
   </div>
<?php endwhile; endif; ?>
</div>

Note: post_class() just calls get_post_class() and outputs it to the browser. post_class() will output something like class="post has-post-thumbnail ..."

Note: I added this to my functions.php :

function thava_add_post_class($classes, $class, $post_id){

    $this_post_class = get_post_meta($post_id, 'thava_post_custom_class', true);
    if (!empty($this_post_class)) {
        $classes[] = $this_post_class; // add this custom class for the post.
    }
    return $classes;        // Return the array
}

add_filter('post_class', 'thava_add_post_class', 10,3);  

Responsive Layout

Tip: Serve big images with more compression. This way, it will expand to fit even retina screens but still not too big in file size.

Tip: use images in different aspect ratios. 5:3 images look better than 1:1 square images. For top bars use images like 10:1 ratio.

Now a days:

Display Size: 5.5 inches
Screen Size: 400 x 700 points
Pixels :     1200 x 2100 pixels (Around Ratio 3x)
                                (1 Point = 3 pixels )
PPI    : 400 pixels per Inch;
  • Browsers return the POINT VALUE OF THE DEVICE — NOT the actual PIXEL VALUE :

    • It is good because it is fairly indicative of size.
    • It is bad because the @media query using px is not aware the device is high density retina device.
  • You should query device-pixel-ratio :

    #element { background-image: url('image1.jpg'); }
    
    @media only screen and (min-device-pixel-ratio: 2) {
        #element { background-image: url('image2.jpg'); }
    }
    
  • For full-width hero images, recommended width is: 750px, 1100px, 1600px, 2800px;

  • Mainly design your website for portrait and landscape views.

  • Ocean Wordpress preview is available for 3 setups:

    • 960 plus size. (boxed max at 1280 size)
    • 768 plus size.
    • 480 plus size.
  • For mobiles, let the image occupy full width and margin be fixed e.g. 10 or 20 px. For big screen you may have big margins.

  • You can hide some images or components selectively on devices:

    @media only screen and (max-width: 767px) {
        .hide-tablet-mobile {
            display: none !important
        }
    }
    @media only screen and (max-width: 480px) {
        .hide-mobile {
            display: none !important
        }
    }
    @media only screen and (min-width: 481px) and (max-width: 767px) {
        .hide-tablet {
            display: none !important
        }
    }
    

For retina screen, you can do :

@media only screen and (-webkit-min-device-pixel-ratio: 2),
        (min-resolution: 192dpi) { /* High-res styles go here */ }

From oceanwp style sheet :

Break points: 1280  959   768     480 
              100%  75%   60%     37.5%

# Changing boxed width from 1280 to 1500 had no effect.

@media only screen and (min-width: 768px) and (max-width: 959px) {
@media only screen and (max-width: 480px) {
     width is 100%;   bottom margin 30 px;

@media only screen and (max-width: 1280px) {
    widget area is 50% of sidebar area;

@media only screen and (max-width: 1080px) {
@media only screen and (max-width: 959px) {
    overflow: hidden; This will make navigation menu hidden ??

@media only screen and (min-width: 768px) and (max-width: 959px) {
@media only screen and (max-width: 480px) {

    User images to be displayed as block;

@media screen and (min-width: 30em) {
@media screen and (min-width: 48em) {
@media print {
   make background transparent;

@media only screen and (max-width: 480px) {
@media only screen and (max-width: 767px) {
@media only screen and (max-width: 959px) {
@media only screen and (max-width: 1280px) {
@media only screen and (min-width: 768px) and (max-width: 1280px) {
    .single-post.media-above-content .thumbnail {
         bottom margin 20 px
@media only screen and (min-width: 481px) and (max-width: 768px) {

Steps Done for thavablog

Initialization

wp core install --url=http://thava.net --title="Data And Technology"  \
        --admin_user=thava --admin_password=thava --admin_email=thavamuni@gmail.com
wp option update category_base topics
wp option update tag_base tag
wp option update permalink_structure  /%category%/%postname%
wp rewrite structure '/%category%/%postname%'  --hard
wp rewrite flush --hard                     f
# cat .htaccess

wp theme install spacious --activate
wp plugin install everest-forms --activate
wp plugin install 'w3-total-cache' --activate
wp plugin install prismatic --activate
wp plugin install title-remover --activate

wp plugin install php-code-widget --activate

wp plugin install woosidebars --activate
wp plugin install widgetlogic --activate    # Same functionality as woosidebars ??

wp plugin install tablepress --activate
wp plugin install debug-bar --activate
wp plugin install query-monitor --activate
wp plugin install show-current-template --activate
wp plugin install insert-headers-and-footers  --activate    # Applies for all pages.
wp plugin install header-and-footer-scripts   --activate    # Applies page specific



https://wordpress.org/plugins/login-lockdown/
https://wordpress.org/plugins/p3-profiler/
https://wordpress.org/plugins/wp-slimstat/   Analytics

wp plugin install tinymce-editor  --activate
wp plugin install black-studio-tinymce-widget  --activate


# See all spacious specific options
wp option get spacious

wp plugin install table-of-contents-plus --activate
wp plugin install astra-hooks --activate
# recomended by generate press ...
wp plugin install code-snippets --activate
wp plugin install pluginception --activate

wp plugin install child-theme-configurator --activate
wp plugin install child-theme-wizard  --activate

Copy page-templater from wpexplorer.com

 wp plugin install ....

 breadcrumb-navxt
 regenerate-thumbnails
 recent-posts-widget-with-thumbnails
 related-posts-thumbnails
 advanced-custom-fields
 crayon-syntax-highlighter
 wp-syntax and enlighter are crayon alternatives
 easy-google-fonts
 enhanced-media-library
 enable-media-replace
 images-optimizer (A/B Testing)
 all-in-one-wp-security-and-firewall
 wps-hide-login
 svg-support
 recent-posts-widget-extended
 wordpress-popular-posts
 widget-css-classes

 shortpixel-image-optimiser

 wp plugin install disable-emojis --activate
 https://wordpress.org/plugins/insert-php/  (now called as php code snippet)
 autoptimize

## Another title another content

Changing upload folder

WP Schema

wp_posts

ID bigint(20) post_author bigint(20) post_date post_date_gmt datetime post_content longtext post_title text post_excerpt text post_status varchar(20) comment_status varchar(20) ping_status varchar(20) post_password varchar(255) post_name varchar(200) to_ping text pinged text post_modified datetime post_modified_gmt datetime post_content_filtered longtext post_parent bigint(20) guid varchar(255) menu_order int(11) post_type varchar(20) post_mime_type varchar(100) comment_count bigint(20)

Example For regular post:

wp post get 55

+-----------------------+-----------------------------------+
| Field                 | Value                             |
+-----------------------+-----------------------------------+
| ID                    | 55                                |
| post_author           | 1                                 |
| post_date             | 2018-10-30 18:36:46               |
| post_date_gmt         | 2018-10-30 18:36:46               |
| post_content          | <h2> ... </h2> ...                |
| post_title            | How to read excel in R program    |
| post_excerpt          |                                   |
| post_status           | publish (inherit, etc)            |
| comment_status        | open                              |
| ping_status           | open                              |
| post_password         |                                   |
| post_name             | how-to-read-excel-in-r-program    |
| to_ping               |                                   |
| pinged                |                                   |
| post_modified         | 2018-10-30 23:37:13               |
| post_content_filtered |                                   |
| post_parent           | 0                                 |
| guid                  | http://thava.net/?p=55            |
| menu_order            | 0                                 |
| post_type             | post                              |
| post_mime_type        |                                   |
| comment_count         | 0                                 |
+-----------------------+-----------------------------------+

Example For media images :

wp post list --post_type=attachment
+----+----------------+----------------+------------------+-------------+
| ID | post_title     | post_name      | post_date        | post_status |
+----+----------------+----------------+------------------+-------------+
| 65 | excel-1920     | excel-1920     | 2018-10-30 20:02 | inherit     |
| 56 | Excel Graphics | excel-640      | 2018-10-30 18:23 | inherit     |
+----+----------------+----------------+------------------+-------------+

wp post get 56

+-----------------------+-----------------------------------------------+
| Field                 | Value                                         |
+-----------------------+-----------------------------------------------+
| ID                    | 56                                            |
| post_author           | 1                                             |
| post_date             | 2018-10-30 18:23:33                           |
| post_content          |                                               |
| post_title            | Excel Graphics                                |
| post_excerpt          |                                               |
| post_status           | inherit                                       |
| post_name             | excel-640                                     |
| post_parent           | 55                                            |
| guid                  | http://thava.net/wp-content/uploads/2018/10/e |
|                       | xcel-640.png                                  |
| menu_order            | 0                                             |
| post_type             | attachment                                    |
| post_mime_type        | image/png                                     |
| ......                | ......                                        |
+-----------------------+-----------------------------------------------+

Note: guid is post url or image url.

select distinct post_type from wp_posts ;
  +---------------------+
  | post_type           |
  +---------------------+
  | acf-field-group     |
  | attachment          |
  | customize_changeset |
  | nav_menu_item       |
  | page                |
  | post                |
  | revision            |
  +---------------------+

Note: Post to attachment information is not present in wp_posts itself. It is there in wp_postmeta table.

wp_postmeta

`meta_id` bigint(20) 
`post_id` bigint(20) 
`meta_key` varchar(255) 
`meta_value` longtext 

What are the meta key possible values ? Can you have 1:N values for some post_id:meta_key, some examples ? :

mysql>  select distinct meta_key from wp_postmeta ;
+-------------------------------------+
| meta_key                            |
+-------------------------------------+
| _wp_page_template                   |
| _menu_item_type                     |
| ..........                          |
| ocean_display_top_bar               |
| ocean_....                          |
| thava_post_class                    |
| inline_featured_image               |
| featured_image_giphy                |
| _wp_attached_file                   |
| _thumbnail_id                       |
| _wp_attachment_metadata             |
+-------------------------------------+

The wp_attachment_metadata is in json format -- encodes all info for one attachment for one post.

wp db query "select * from wp_postmeta where post_id = 55 " :

+---------+---------+----------------------+----------------+
| meta_id | post_id | meta_key             | meta_value     |
+---------+---------+----------------------+----------------+
|     151 |      55 | spacious_page_layout | default_layout |
|     152 |      55 | _thumbnail_id        | 56             |
|     153 |      55 | _wp_page_template    | default        |
|     216 |      55 | wptr_hide_title      | 1              |
|     387 |      55 | _edit_lock           | 1541969036:1   |
+---------+---------+----------------------+----------------+

A post is related to featured image using thumbnail_id entry in postmeta table. The thumbnail_id value 56 is a post_id of the image. Even the post is associated with page template etc which is valid when that post is displayed as single post.

If no post refers to image, then there is no thumbnail_id that exists.

To get all info related to that thumbnail, we need to lookup both wp_posts and wp_postmeta tables.

wp get post 56 :

+-----------------------+-----------------------------------------------+
| Field                 | Value                                         |
+-----------------------+-----------------------------------------------+
| ID                    | 56                                            |
| post_name             | excel-640                                     |
| post_parent           | 55        // this is 0 if unattached image.   |
| guid                  | http://thava.net/wp-content/uploads/2018/10/e |
|                       | xcel-640.png                                  |
| post_type             | attachment                                    |
| post_mime_type        | image/png                                     |
| ......                | ......                                        |
+-----------------------+-----------------------------------------------+

wp db query "select * from wp_postmeta where post_id = 56 " :

+---------+---------+--------------------------+----------------------
| meta_id | post_id | meta_key                 | meta_value   
+---------+---------+--------------------------+----------------------
|     148 |      56 | _wp_attached_file        | 2018/10/excel-640.png
|     149 |      56 | _wp_attachment_metadata  | .....
|     150 |      56 | _wp_attachment_image_alt | Excel Graphics
+---------+---------+--------------------------+----------------------

Note: This image has a relative path which is _wp_attached_file;

wp post meta get 56 wp_attachment_metadata :

array (
 'width' => 640, 'height' => 479,
 'file' => '2018/10/excel-640.png', // Duplicate info.
 'image_meta' =>                    // See Also: _wp_attached_file.
               array ( ...
                 'title' => '',
                 'keywords' => array (),
               ),
)

There is a way to get this info from wp cli :

wp post meta pluck <attachment_id> <key> <key-path>... [--format=<format>]
Note: attachment_id is same as post_id of the image.

$ wp post meta pluck  56 _wp_attachment_metadata file  
  2018/10/excel-640.png

$ wp post meta get  56 _wp_attached_file
  2018/10/excel-640.png

But if you want to get width x height info, there is only one way :

$ wp post meta pluck  56 _wp_attachment_metadata width
$ wp post meta pluck  56 _wp_attachment_metadata height

wp_options

option_id bigint(20) option_name varchar(191) option_value longtext

wp_comments

`comment_ID` bigint(20)
`comment_post_ID` bigint(20) 
`comment_author` tinytext 
`comment_author_email` varchar(100)

wp_commentmeta

meta_id, comment_id, meta_key varchar, meta_value longtext

`link_id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`link_url` varchar(255) 
`link_name` varchar(255) 
`link_image` varchar(255) 
`link_target` varchar(25) 

more tables:

wp_commentmeta.sql    wp_links.sql     wp_term_relationships.sql
wp_commentmeta.txt    wp_links.txt     wp_term_relationships.txt
wp_comments.sql       wp_options.sql   wp_terms.sql
wp_comments.txt       wp_options.txt   wp_terms.txt
wp_evf_entries.sql    wp_postmeta.sql  wp_term_taxonomy.sql
wp_evf_entries.txt    wp_postmeta.txt  wp_term_taxonomy.txt
wp_evf_entrymeta.sql  wp_posts.sql     wp_usermeta.sql
wp_evf_entrymeta.txt  wp_posts.txt     wp_usermeta.txt
wp_evf_sessions.sql   wp_termmeta.sql  wp_users.sql
wp_evf_sessions.txt   wp_termmeta.txt  wp_users.txt

Customizing single post

To customize each post, get all meta information related to that post:

$ wp post meta get 56 <meta-key>  # No way to list all meta without query.
$ wp db query "select meta_id, post_id, meta_key, meta_value 
                from wp_postmeta where post_id = $1 " 
+---------+---------+-------------------------------------+--------------------+
| meta_id | post_id | meta_key                            | meta_value         |
+---------+---------+-------------------------------------+--------------------+
|     292 |      56 | thava_post_class                    | thava_max_width300 |
|     201 |      56 | ocean_sidebar                       | 0                  |
|     202 |      56 | ocean_second_sidebar                | 0                  |
|     203 |      56 | ocean_disable_margins               | enable             |
|     204 |      56 | ocean_display_top_bar               | default            |
|     205 |      56 | ocean_display_header                | default            |
|     206 |      56 | ocean_center_header_left_menu       | 0                  |
|     207 |      56 | ocean_custom_header_template        | 0                  |
|     208 |      56 | ocean_header_custom_menu            | 0                  |
|     209 |      56 | ocean_menu_typo_font_family         | 0                  |
|     210 |      56 | ocean_disable_title                 | default            |
|     211 |      56 | ocean_disable_heading               | default            |
|     212 |      56 | ocean_disable_breadcrumbs           | default            |
|     213 |      56 | ocean_display_footer_widgets        | default            |
|     214 |      56 | ocean_display_footer_bottom         | default            |
|     215 |      56 | ocean_custom_footer_template        | 0                  |
|     216 |      56 | ocean_link_format_target            | self               |
|     217 |      56 | ocean_quote_format_link             | post               |
|     310 |      56 | _syntaxhighlighter_encoded          | 1                  |
|     352 |      56 | inline_featured_image               | 0                  |
|     353 |      56 | images-optimizer__alpha_image_giphy | 0                  |
|     354 |      56 | featured_image_giphy                | 0                  |
|     355 |      56 | images-optimizer__status            | on                 |
|     356 |      56 | images-optimizer__beta_image        |                    |
+---------+---------+-------------------------------------+--------------------+

To add custom advanced field for specific post do:

wp post meta update <post_id> thava_post_class "thava_max_width300"      

Supported image sizes and cropping

it is not in the database
// Standard sizes
$image_sizes = array('thumbnail', 'medium', 'medium_large', 'large'); 

In addition wp-includes/media.php defines: set_post_thumbnail_size():
  add_image_size( 'post-thumbnail', $width, $height, $crop );      

Global variables

Admin Globals
$pagenow (string) used in wp-admin 
     See also get_current_screen() for the WordPress Admin Screen API
$post_type (string) used in wp-admin
$allowedposttags (array)
$allowedtags (array)
$menu (array

Case Study: Jonathan Soma Site

Include bootstrap min.css :

href="https://maxcdn...bootstrap.min.css"
href="https://maxcdn...bootstrap-theme.min.css"

href="https://maxcdn...font-awesome.min.css"

<link rel="stylesheet" href="/css/new.css">

<link rel="alternate" type="application/rss+xml" 
   title="Things by Jonathan Soma" href="../../feed.xml" />

href="/css/pygments/zenburn.css"

Bootstrap Grid System

Devices   resolution  class prefix:

Extra small devices    Phones (<768px)     .col-xs-*
Small devices          Tablets (≥768px)    .col-sm-*
Medium devices         Desktops (≥992px)   .col-md-*
Large devices          Desktops (≥1200px)  .col-lg-*

Typical Use cases:

Use Case                                    Use Class

sidebar on all devices                col-xs-* col-sm-*
sidebar only on Tablet and above:     col-sm-*
hide sidebar on phone                 col-xs-*  { .hide }
3 divisions only on large desktop     col-md-6 col-lg-4
2 divisions on all Tablet and above   col-sm-6 suffices.
On Mobile I want single division      col-xs-12
Full width div                        No class.

Note: Depending on device col-md- overrides col-sm- or vice versa. The media query css, takes care of forcing width=50% vs width=30% depending on viewport size. On 12-column grid, col-lg-4 causes 3 divisions.

To force only 2 divisions on Tablet and above: * using col-sm-6 alone suffices. * However col-sm-6 col-md-6 col-lg-6 is used for readability ??

The order of @media queries is important, the later ones override the earlier ones.

htaccess rules

<IfModule mod_rewrite.c>

    RewriteEngine On
    RewriteBase /                        # Applies to /*

    RewriteRule ^index\.php$ - [L]       # index.php matches.
    # RewriteRule terminates match. New matching starts.

    RewriteCond %{REQUEST_FILENAME} !-f  # File Not exists
    RewriteCond %{REQUEST_FILENAME} !-d  # Dir Not exists
    RewriteRule . /index.php [L]         # Apply this rule.

</IfModule>

Redirect http://sub.domain.com/ to
         http://domain.com/subdomains/sub/

RewriteEngine on
RewriteCond %{HTTP_HOST} ^sub.domain.com
RewriteRule ^(.*)$ http://domain.com/subdomains/sub/$1 [L,NC,QSA]

For a more general rule (that works with any subdomain) ...

RewriteEngine on
RewriteCond %{HTTP_HOST} ^(.*)\.domain\.com
RewriteRule ^(.*)$ http://domain.com/subdomains/%1/$1 [L,NC,QSA]
-----------------------------------

RewriteCond "%{REMOTE_HOST}"  "^host1"  [OR]
RewriteCond "%{REMOTE_HOST}"  "^host2"  [OR]    # OR condition
RewriteCond "%{REMOTE_HOST}"  "^host3"
RewriteRule ...some special stuff for any of these hosts...

Note: %1 matches for previous rule ref.
      $1 matches with same rule.
      QSA - Query string append. Preserve query string ?xxxx=yyy
      L   - Last rule
      NC  - No Case - case insensitive
      C   - (chained with next rule)
      F (forbidden - sends a 403 header to the user)
      N (next - continue processing rules)
      R (temporary redirect to new URL)
      R=301 (permanent redirect to new URL) # Do not use.
      S=3   If current rule matches skip next 3 rules.

External Redirect .php files to .html files (SEO friendly)
   RewriteRule ^(.*)\.php$ /$1.html [R=301,L]

Internal Redirect .html to internal .php 
   RewriteRule ^(.*)\.html$ $1.php [L]

Drop query string.

     RewriteCond %{QUERY_STRING} .           # matches anything.
     RewriteRule ^login\.php /login.php? [L] # No QSA 

Variables Used:      Example Value

THE_REQUEST          "GET /index.html HTTP/1.1"
REQUEST_URI           /index.html
REQUEST_FILENAME      /var/www/abc.com/topic
REQUEST_FILENAME      /var/www/abc.com/topic

HTTP_REFERER and bandwidth theft

When user clicks on a link, like, google, or from document, it sends this field in header. It is also sent when image is retrieved for your page or for some one else's page.

Many blogs publish their referrers. Referrer spams involve fake referral links to boost mutual visibility.

RewriteCond %{HTTP_REFERER} !^$    # Not empty
RewriteCond %{HTTP_REFERER} !^http(s)?://(www\.)?yourwebsite.com [NC]
RewriteCond %{HTTP_REFERER} !^http(s)?://(www\.)?yourotherwebsite.com [NC]
# Redirect to imgur or include dummy image. "Do not hotlink!"
RewriteRule \.(jpg|jpeg|png|gif)$ http://i.imgur.com/MlQAH71.jpg [NC,R,L]

# Block some domains ....

# Do this in .htaccess only with in wp-admin like folders.
RewriteEngine On  
RewriteBase /  
# Inside wp-admin, Referer must be set ...
SetEnvIfNoCase Referer "^$" bad_user        # 
SetEnvIfNoCase User-Agent "^badbot1" bad_user
SetEnvIfNoCase User-Agent "^badbot2" bad_user
SetEnvIfNoCase User-Agent "^badbot3" bad_user
Deny from env=bad_user

Redirect to https
RewriteCond %{HTTPS} !on
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI}

htpasswd -c ~/.htpasswd thava

Use these

 RewriteRule ^wp-admin/includes/ - [F,L]
 RewriteRule ^wp-includes/[^/]+\.php$ - [F,L]

Understand Apache Order Deny,Allow Rules

After apache 2.4, it is now RequireAll, Any, None; See https://stackoverflow.com/questions/9943042/htaccess-order-deny-allow-deny

::
<Limit GET POST> order deny,allow # Allow by default. Deny rules follow ... deny from 186.214.51.231 deny from 186.237.225.26 ... order allow,deny # Deny by default. Allow rules follow ... allow from 186.237.225.26 </Limit>

Best CSS Libs

what is flex: none ?

Is there a difference between flex: none and leaving the flex undefined?

flex: none is equivalent to flex: 0 0 auto, which is shorthand for:

flex-grow: 0
flex-shrink: 0
flex-basis: auto

Simply put, flex: none sizes the flex item according to the width / height of the content, but doesn't allow it to shrink. This means the item has the potential to overflow the container.

If you omit the flex property (and longhand properties), the initial values are as follows:

flex-grow: 0
flex-shrink: 1
flex-basis: auto

This is known as flex: initial.

This means the item will not grow when there is free space available (just like flex: none), but it can shrink when necessary (unlike flex: none).

box-sizing : border-box

Allows to properly include both padding and margin into size of the div box. Bootstrap defines it for all elements * { box-sizing : border-box } Bootstrap rows are also defined with margin -15px for left and right.

view port sizing

vw: 1/100th viewport width
vh: 1/100th viewport height
vmin: 1/100th of the smallest side
vmax: 1/100th of the largest side
Note: IE9 uses vm instead of vmin. It does not support vmax.

Just to clarify: 1vmax equals 1vh in portrait mode, whilst in landscape
mode, 1vmax will equal 1vw.

To Do

  • Compare Theme Page Templates Capabilities

  • Prepare page:

    wp post generate --count=5
    curl http://loripsum.net/api/5 | wp post generate --post_content --count=5
    curl http://loripsum.net/api/5 | wp post generate --post_content --post_type=page --count=4
    
  • Compare the look between Astra, Generate Press, ... , ...

  • Compare the Ready made page templates Available between themes and plugins.

  • Take css files of each theme and apply as custom css on Astra/....

  • Create some custom content with beautification using elementor. Disable elementor and view content.

  • Compare HTML site IDEs:

    • Bootstrapstudio.io Pingendo.com Pinegrow.com
  • Compare