CSS Normalize/Reset for WordPress
While working through the process of optimizing my themes for the newer default WordPress Editor, I noticed some issues when using the CSS Reset that I’ve used and shared in a previous post. I will cover the key steps in that process in a later post, but one of the main aspects was updating my reset method to be less heavy-handed with the newer post blocks. The reset below combines parts of Normalize.css and my previous reset, without totally zeroing out all elements, and as before, it makes form elements and media items responsive.
This is my current CSS Normalize/Reset for WordPress.
html {
box-sizing: border-box;
font-family: system-ui, sans-serif;
line-height: 1.25;
-webkit-text-size-adjust: 100%;
-webkit-tap-highlight-color: transparent;
}
*,
*:before,
*:after {
box-sizing: inherit;
}
body {
margin: 0;
}
h1 {
font-size: 2em;
margin: 0.67em 0;
}
hr {
box-sizing: content-box;
height: 0;
}
pre,
code {
font-family: monospace, monospace;
font-size: 0.937em;
}
pre {
tab-size: 4;
overflow: auto;
}
strong,
b {
font-weight: 700;
}
blockquote,
q {
font-style: italic;
}
ol,
ul {
list-style: none;
padding: 0;
margin: 0;
}
sub,
sup {
font-size: 0.75em;
line-height: 0;
position: relative;
vertical-align: baseline;
}
sub {
bottom: -0.25em;
}
sup {
top: -0.5em;
}
table {
border-collapse: collapse;
border-spacing: 0;
}
th,
td {
border: 1px solid;
padding: 0.25em;
}
button,
input,
optgroup,
select,
textarea {
font-family: inherit;
font-size: 1em;
line-height: inherit;
margin: 0;
}
button,
input,
textarea {
background-color: inherit;
color: inherit;
border: 1px solid;
border-radius: 0;
outline: 0;
padding: 0.25em;
max-width: 100%;
-webkit-appearance: none;
-moz-appearance: none;
}
button,
select {
text-transform: none;
}
::-webkit-search-decoration,
::-webkit-search-cancel-button {
-webkit-appearance: none;
}
progress {
vertical-align: baseline;
}
summary {
display: list-item;
}
blockquote,
figure {
margin-left: 0;
margin-right: 0;
}
details,
audio,
img,
video {
display: block;
}
img,
video {
height: auto;
max-width: 100%;
}
embed,
iframe,
object {
max-width: 100%;
}
.alignleft {
float: left;
margin: 0 1em 1em 0;
}
.alignright {
float: right;
margin: 0 0 1em 1em;
}
.aligncenter {
clear: both;
display: block;
margin-left: auto;
margin-right: auto;
}
.clear {
clear: both;
}
.screen-reader-text {
border: 0;
clip: rect(1px, 1px, 1px, 1px);
-webkit-clip-path: inset(50%);
clip-path: inset(50%);
height: 1px;
margin: -1px !important;
overflow: hidden;
padding: 0;
position: absolute !important;
width: 1px !important;
word-wrap: normal !important;
}
.bypostauthor{}
.gallery-caption{}
.sticky{}
.wp-caption-text{}
.wp-caption{}
This is a minified version of the code above.
html{box-sizing:border-box;font-family:system-ui,sans-serif;line-height:1.25;-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:transparent}*,*:before,*:after{box-sizing:inherit}body{margin:0}h1{font-size:2em;margin:.67em 0}hr{box-sizing:content-box;height:0}pre,code{font-family:monospace,monospace;font-size:.937em}pre{tab-size:4;overflow:auto}strong,b{font-weight:700}blockquote,q{font-style:italic}ol,ul{list-style:none;padding:0;margin:0}sub,sup{font-size:.75em;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{border-collapse:collapse;border-spacing:0}th,td{border:1px solid;padding:.25em}button,input,optgroup,select,textarea{font-family:inherit;font-size:1em;line-height:inherit;margin:0}button,input,textarea{background-color:inherit;color:inherit;border:1px solid;border-radius:0;outline:0;padding:.25em;max-width:100%;-webkit-appearance:none;-moz-appearance:none}button,select{text-transform:none}::-webkit-search-decoration,::-webkit-search-cancel-button{-webkit-appearance:none}progress{vertical-align:baseline}summary{display:list-item}blockquote,figure{margin-left:0;margin-right:0}details,audio,img,video{display:block}img,video{height:auto;max-width:100%}embed,iframe,object{max-width:100%}.alignleft{float:left;margin:0 1em 1em 0}.alignright{float:right;margin:0 0 1em 1em}.aligncenter{clear:both;display:block;margin-left:auto;margin-right:auto}.clear{clear:both}.screen-reader-text{border:0;clip:rect(1px,1px,1px,1px);-webkit-clip-path:inset(50%);clip-path:inset(50%);height:1px;margin:-1px!important;overflow:hidden;padding:0;position:absolute!important;width:1px!important;word-wrap:normal!important}.bypostauthor{}.gallery-caption{}.sticky{}.wp-caption-text{}.wp-caption{}
Adding Widgets to the Footer in WordPress
Widgets are great for adding dynamic content to WordPress sites like Recent Posts, Archives, Custom HTML, etc. The method below adds three widgets to the site’s footer area. The widgets stack on top of each other when the viewport is less than 769px wide, then at 769px or wider, they divide into three equal width columns. They also only affect the layout if one or more widgets are active.
Start by adding this to the theme’s functions.php file.
<?php
function emit_widgets_init() {
register_sidebar( array(
'name' => esc_html__( 'Footer 1', 'emit' ),
'id' => 'footer-1',
'description' => esc_html__( 'Add widgets here.', 'emit' ),
'before_widget' => '<div id="%1$s" class="widget widget-1 %2$s">',
'after_widget' => '</div>',
'before_title' => '<h4 class="widget-title">',
'after_title' => '</h4>',
) );
register_sidebar( array(
'name' => esc_html__( 'Footer 2', 'emit' ),
'id' => 'footer-2',
'description' => esc_html__( 'Add widgets here.', 'emit' ),
'before_widget' => '<div id="%1$s" class="widget widget-2 %2$s">',
'after_widget' => '</div>',
'before_title' => '<h4 class="widget-title">',
'after_title' => '</h4>',
) );
register_sidebar( array(
'name' => esc_html__( 'Footer 3', 'emit' ),
'id' => 'footer-3',
'description' => esc_html__( 'Add widgets here.', 'emit' ),
'before_widget' => '<div id="%1$s" class="widget widget-3 %2$s">',
'after_widget' => '</div>',
'before_title' => '<h4 class="widget-title">',
'after_title' => '</h4>',
) );
}
add_action( 'widgets_init', 'emit_widgets_init' );
Then add this to the theme’s footer.php file.
<div id="footer-widgets">
<?php
if( is_active_sidebar( 'footer-1' ) ) {
dynamic_sidebar( 'footer-1' );
}
if( is_active_sidebar( 'footer-2' ) ) {
dynamic_sidebar( 'footer-2' );
}
if( is_active_sidebar( 'footer-3' ) ) {
dynamic_sidebar( 'footer-3' );
}
?>
</div>
<div class="clear"></div>
Finally, add the CSS below to the theme’s existing stylesheet.
@media (min-width: 769px) {
.widget-1,
.widget-2 {
float: left;
width: 30%;
margin-right: 5%;
}
.widget-3 {
float: left;
width: 30%;
}
}
.clear {
clear: both;
}
Get the First or Featured Image URL in WordPress
In a previous post I covered how to get the first or Featured Image in WordPress for displaying the image, but sometimes just the image URL is needed for Open Graph and Twitter Card header tags, etc. The method below first checks for a Featured Image, then for the first attached image, and finally a default image if needed. This also allows you to designate the size (thumbnail, medium, large or full), and it outputs the image URL without the img tag and associated image attributes.
<?php
function evo_thumbnail_image_url() {
if ( has_post_thumbnail() ) {
the_post_thumbnail_url( 'large' );
} else {
global $post;
$args = array(
'post_type' => 'attachment',
'numberposts' => -1,
'post_mime_type' => 'image',
'post_status' => null,
'post_parent' => $post->ID,
'posts_per_page' => 1
);
$attachments = get_posts( $args );
if ( $attachments ) {
foreach ( $attachments as $attachment ) {
$src = wp_get_attachment_image_src( $attachment->ID, 'large' );
if ( $src ) {
echo $src[0];
}
}
} else {
echo get_stylesheet_directory_uri() . '/assets/images/default-post-image.png';
}
}
}
Use the function in the loop like this.
<?php evo_thumbnail_image_url(); ?>
If only the Featured Image URL is needed, the method below will work.
<?php the_post_thumbnail_url( 'large' ); ?>
Current Prism Syntax Highlighter Theme
In a previous post I covered how I added Prism syntax highlighter to this blog to style the posted code blocks. It really makes a world of difference in the readability of code within the posts on here, so I decided to make my own Prism theme. I based my Monokai Mod theme off of the classic Monokai theme, but I shifted the grey tones and softened the colors. The theme is live on the blog now, and the CSS is posted below. I’ll update this post over time, as the theme will most likely evolve.
/*
Monokai Mod - a theme for PrismJS
URL: https://github.com/e33io/webdev/blob/main/prism.css
For WordPress, copy the theme file here: assets/prism/prism.css, and use the
Code Syntax Block plugin (https://wordpress.org/plugins/code-syntax-block)
*/
:root {
--mm-red: #fc618d;
--mm-orange: #fd9353;
--mm-yellow: #fce566;
--mm-green: #7bd88f;
--mm-cyan: #53e1e2;
--mm-blue: #78c5eb;
--mm-pink: #ff79c6;
--mm-purple: #948ae3;
--mm-grey12: #1e1e1e;
--mm-grey15: #252525;
--mm-grey21: #353535;
--mm-grey30: #4d4d4d;
--mm-grey33: #535353;
--mm-grey42: #6c6c6c;
--mm-grey50: #7f7f7f;
--mm-grey67: #aaaaaa;
--mm-grey80: #cccccc;
--mm-grey87: #dddddd;
--mm-grey93: #eeeeee;
}
code[class*="language-"],
pre[class*="language-"] {
color: var(--mm-grey93);
background: none;
font-family: var(--monospace, monospace);
font-size: 0.937rem;
text-align: left;
white-space: pre;
word-spacing: normal;
word-break: normal;
word-wrap: normal;
line-height: 1.5;
tab-size: 4;
hyphens: none;
}
/* code blocks */
pre[class*="language-"] {
padding: 1rem;
overflow: auto;
border-radius: 0;
}
:not(pre) > code[class*="language-"],
pre[class*="language-"] {
background: var(--block-color, var(--mm-grey15));
}
/* inline code */
:not(pre) > code[class*="language-"] {
border-radius: 0.25rem;
padding: 1px 4px;
white-space: normal;
}
/* minified code blocks */
pre.minified code {
word-wrap: break-word;
word-break: break-all;
white-space: pre-wrap;
}
/* scrollbars */
pre::-webkit-scrollbar {
height: 0.66rem;
width: 0.66rem;
}
pre::-webkit-scrollbar-thumb {
background-color: var(--mm-grey42);
}
pre::-webkit-scrollbar-track {
background-color: var(--mm-grey30);
}
/* tokens */
.token.comment,
.token.prolog,
.token.doctype,
.token.cdata {
color: var(--mm-grey42);
}
.token.punctuation {
color: var(--mm-grey80);
}
.namespace {
opacity: 0.7;
}
.token.property,
.token.tag,
.token.constant,
.token.symbol,
.token.deleted {
color: var(--mm-blue);
}
.token.boolean,
.token.number {
color: var(--mm-purple);
}
.token.selector,
.token.attr-name,
.token.char,
.token.builtin,
.token.inserted {
color: var(--mm-green);
}
.token.string {
color: var(--mm-yellow);
}
.token.operator,
.token.entity,
.token.url,
.token.variable {
color: var(--mm-cyan);
}
.token.atrule,
.token.attr-value,
.token.function,
.token.class-name {
color: var(--mm-green);
}
.token.keyword,
.language-css .token.important {
color: var(--mm-red);
}
.token.regex,
.token.important {
color: var(--mm-orange);
font-weight: 400;
}
.token.italic,
.token.comment {
font-style: italic;
}
.token.entity {
cursor: help;
}
.prism-titlename {
float: right;
margin: -0.85rem -0.75rem;
font-size: 0.66rem;
text-transform: uppercase;
color: var(--mm-grey50);
}
Note that (in the theme above) a lot of the token classes are grouped to single colors, so the color pallet could be easily expanded if needed.
Customize the WordPress Login Page with Your Site Icon
The default WordPress login page works perfectly fine, but it’s branded with their icon and the icon links to wordpress.org. Rebranding this page with your Site Icon helps make the login experience custom to your site. The method below uses the site_icon_url() for the background-image: url(), displaying your Site Icon in place of the WordPress icon, and links it to your site’s home page instead of wordpress.org.
Add this to the theme’s functions.php file.
<?php
function evo_login_icon() { ?>
<style type="text/css">
.login h1 a {
background-image: url( <?php site_icon_url() ?> );
background-size: contain;
width: 90px;
height: 90px;
border-radius: 45px;
}
</style>
<?php }
add_action( 'login_head', 'evo_login_icon' );
function evo_login_url() {
return '/';
}
add_filter( 'login_headerurl', 'evo_login_url' );
Now your Site Icon will display on the login screen and it will link to your site’s home page.
