-
Notifications
You must be signed in to change notification settings - Fork 0
Factor1 Misc Practices Snippets
At Factor1 we use BEM naming conventions to handle class names wherever we can. Done well, it makes for streamlined SCSS styles that compile nicely.
Read up on BEM here.
<article class="blog-post">
<a href="<?php the_permalink(); ?>">
<div class="blog-post__img" style="background: url('<?php echo featuredURL('post_grid'); ?>') center/cover no-repeat"></div>
<div class="blog-post__title">
<h6><?php the_title(); ?></h6>
</div>
</a>
</article>
.blog-post {
flex-basis: 30% !important;
margin-top: 30%;
margin-bottom: rem(20);
a {
position: relative;
display: block;
height: 100%;
text-decoration: none;
}
&__img {
position: absolute;
bottom: 80%;
width: 100%;
padding-bottom: 100%;
}
&__title {
position: relative;
display: flex;
align-items: center;
width: 70%;
height: 100%;
margin: 0 auto;
padding: rem(15) rem(20);
box-shadow: 0 0 rem(5) rgba($black, 0.35);
background-color: $white;
z-index: 1;
transition: all .4s ease;
}
}
We do not use iframes as background videos, ever, due to issues they can cause. For background videos, use an ACF File field (be sure to restrict the file type to .mp4 files).
<?php
/*
* Hero (global)
*
* Template part used on various templates/views
*
* @package F1 Project Name
* @author Factor1 Studios
* @since 0.0.1
*/
// Hero Custom Fields
$img = wp_get_attachment_image_src(get_post_thumbnail_id(), 'hero');
$videoToggle = get_field('hero_video_toggle');
$video = get_field('hero_video');
$headline = get_field('hero_headline');
$align = get_field('hero_alignment'); // left or center ?>
<section class="hero" style="background: url('<?php echo $img[0]; ?>') center/cover no-repeat">
<?php // Optional video
if( $videoToggle ) : ?>
<div class="hero--home__video sm-hide">
<video autoplay loop muted class="sm-hide">
<source src="<?php echo $video; ?>" type="video/mp4">
</video>
</div>
<?php endif; ?>
<div class="container">
<div class="row">
<div class="col-12 text-<?php echo $align; ?>">
<h1><?php echo $headline; ?></h1>
</div>
</div>
</div>
</section>
/*
* Hero (global)
*
* Template part used on various templates/views
*
* @package F1 Project Name
* @author Factor1 Studios
* @since 0.0.1
*/
.hero {
position: relative;
@include iPhoneX;
overflow: hidden;
// Optional video
&__video {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
video {
position: absolute;
top: 50%;
left: 50%;
min-width: 100%;
min-height: 100%;
width: auto;
height: auto;
transform: translateX(-50%) translateY(-50%);
}
.container {
padding: rem(270) 0 rem(105);
}
&:after {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: linear-gradient(to bottom, rgba(0, 0, 0, .9), rgba(0, 0, 0, 0) 35%);
}
}
.touch .hero__video,
.touch .hero__video video {
display: none;
}
// Media Queries
@media screen and (max-width: $small-breakpoint) {
.hero .container {
padding: rem(200) 0 rem(70);
}
}
We include a customized admin for every site we build. It doesn’t have to be anything super fancy, but including brand colors and their logo is a nice touch.
Below is a snippet that you can customize as needed. This snippet we generally include in inc/tweaks.php
:
// Customize Wordpress Admin
// add login logo
function custom_loginlogo() {
echo '<style type="text/css">
.login {
background: #07223a;
background: linear-gradient(to right, #07223a, #1679af, #1679af, #07223a);
}
.login .message,
.login #login_error {
margin-top: 30px;
border-color: #e9b730;
}
.login p a {
color: #fff !important;
transition: all .4s ease;
}
.login p a:hover {
color: #e9b730 !important;
}
.login input[type="text"]:active,
.login input[type="text"]:focus,
.login input[type="password"]:active,
.login input[type="password"]:focus,
input[type=text]:focus,
input[type=search]:focus,
input[type=radio]:focus,
input[type=tel]:focus,
input[type=time]:focus,
input[type=url]:focus,
input[type=week]:focus,
input[type=password]:focus,
input[type=checkbox]:focus,
input[type=color]:focus,
input[type=date]:focus,
input[type=datetime]:focus,
input[type=datetime-local]:focus,
input[type=email]:focus,
input[type=month]:focus,
input[type=number]:focus,
select:focus,
textarea:focus {
border-color: #1679af;
}
.login input[type="submit"] {
background-color: #1679af;
border-color: #1679af;
box-shadow: 0 1px 0 #1679af;
text-shadow: none;
}
.login input[type="submit"]:hover {
background-color: #1679af;
}
h1 a {
height: 100% !important;
width:100% !important;
background-image: url(' . get_template_directory_uri() . '/assets/img/logo.svg) !important;
background-postion-x: center !important;
background-size:contain !important;
margin-bottom:10px !important;
}
h1 {
width: 320px !important;
Height: 120px !important
}
</style>';
}
add_action('login_head', 'custom_loginlogo');
// add custom footer text
function modify_footer_admin () {
echo 'Created by <a href="https://factor1studios.com">factor1</a>. ';
echo 'Powered by<a href="https://WordPress.org">WordPress</a>.';
}
add_filter('admin_footer_text', 'modify_footer_admin');
This function will add the theme's colors to WYSIWYG editors for easy text editing. Add this function to inc/tweaks.php
:
// Add custom colors to wysiwygs
function custom_editor_colors($init) {
$custom_colors = '
"DBDBDB", "Light Gray",
"FFFFFF", "White",
// ... add rest of theme colors here
';
// build colour grid default+custom colors
$init['textcolor_map'] = '['.$custom_colors.']';
// change the number of rows in the grid if the number of colors changes
// 8 swatches per row
$init['textcolor_rows'] = 1;
return $init;
}
add_filter('tiny_mce_before_init', 'custom_editor_colors');
Important! Do not forget to client-proof this functionality and safeguard how white/light text appears in WYSYWYG editors:
In dist/editor-styles.css
:
/* Do not change this! This ensures that white text remains visible in admin WYSIWYG editors */
span[style*="color: #ffffff"],
span[style*="color: #ffffff;"],
span[style*="color: #f5f5f5"],
span[style*="color: #f5f5f5;"] {
color: #dbdbdb !important;
}
For sites that have some custom typography classes, it’s a good idea to add them as options in the WYSIWYG editors.
It’s also a good idea to include a stylesheet to handle the classes’ appearance in the WYSIWYG editors. You don’t need to load the fonts necessarily, and we avoid using white as a text color in the editors, but some visual indication is helpful for clients.
inc/tweaks.php
is a good home for these snippets.
// Add custom classes to WYSIWYGs
function custom_wysiwyg_options( $init_array ) {
$style_formats = array(
array(
'title' => 'Support',
'block' => 'h3',
'classes' => 'support',
'wrapper' => false,
),
);
// Insert the array, JSON ENCODED, into 'style_formats'
$init_array['style_formats_merge'] = true;
$init_array['style_formats'] = wp_json_encode( $style_formats );
return $init_array;
}
// add_filter( 'tiny_mce_before_init', 'custom_wysiwyg_options' );
// Add editor styles from custom wysiwyg options
function custom_editor_styles() {
add_editor_style('/assets/css/editor-styles.min.css');
}
// add_action('init', 'custom_editor_styles');
Add this in inc/tweaks.php
:
// Add async defer to font awesome script
function add_async_attribute($tag, $handle) {
if ( 'font-awesome' !== $handle )
return $tag;
return str_replace( ' src', ' async="async" src', $tag );
}
add_filter('script_loader_tag', 'add_async_attribute', 10, 2);
Due to some changes in the url structure for Google fonts, enqueuing more than one family can cause some fonts to drop.
To avoid this issue, make sure to pass an empty array for dependencies and set the version to null
in the enqueue
function.
// inc/enqueues.php
wp_enqueue_style('google-fonts', 'https://fonts.googleapis.com/css2?family=Montserrat:ital,wght@0,300;0,400;0,500;0,600;0,700;1,300;1,400;1,500;1,600;1,700;1,800&display=swap', array(), null);
Add the following snippet to inc/tweaks.php
. It will add a column to the pages list view in the WP admin showing what template is used on each page:
// Display page templates in admin
add_filter( 'manage_pages_columns', 'page_column_views' );
add_action( 'manage_pages_custom_column', 'page_custom_column_views', 5, 2 );
function page_column_views( $defaults ) {
$defaults['page-layout'] = __('Template');
return $defaults;
}
function page_custom_column_views( $column_name, $id ) {
if ( $column_name === 'page-layout' ) {
$set_template = get_post_meta( get_the_ID(), '_wp_page_template', true );
if ( $set_template == 'default' ) {
echo 'Default';
}
$templates = get_page_templates();
ksort( $templates );
foreach ( array_keys( $templates ) as $template ) :
if ( $set_template == $templates[$template] ) echo $template;
endforeach;
}
}
First, add an admin thumbnail size in inc/thumbnails.php
:
if( function_exists('prelude_features') ){
// Use add_image_size below to add additional thumbnail sizes
add_image_size( 'admin_thumb', 75, 75, array('center', 'center') );
...
}
Then, add the following snippet to inc/tweaks.php
. It will add a column to the posts list view in the WP admin their featured images (this can also be adapted to add to page views and other CPTs):
// Display featured images in admin list
// Add the posts and pages columns filter. They both use the same function.
add_filter('manage_posts_columns', 'add_post_admin_thumbnail_column', 2);
// Add the column
function add_post_admin_thumbnail_column($columns) {
$columns['admin_thumb'] = __('Featured Image');
return $columns;
}
// Manage Post and Page Admin Panel Columns
add_action('manage_posts_custom_column', 'show_post_thumbnail_column', 5, 2);
// add_action('manage_pages_custom_column', 'show_post_thumbnail_column', 5, 2); // Uncomment this to show page featured images
// Get featured-thumbnail size post thumbnail and display it
function show_post_thumbnail_column($columns, $id) {
switch($columns){
case 'admin_thumb':
if( function_exists('the_post_thumbnail') ) {
echo the_post_thumbnail( 'admin_thumb' );
}
else
echo 'hmm… your theme doesn\'t support featured image…';
break;
}
}
We can only guarantee our own, QA-tested code. So to prevent clients from adding anything that causes issues or conflicts, we disable the Additional CSS option from the WordPress Customizer as well as the Theme and Plugin file editors.
Add these snippets to inc/tweaks.php
:
// Remove additional css option from customizer
function prefix_remove_css_section( $wp_customize ) {
$wp_customize->remove_section( 'custom_css' );
}
add_action( 'customize_register', 'prefix_remove_css_section', 15 );
// Remove theme/plugin editors from admin
define( 'DISALLOW_FILE_EDIT', true );
We have developed a streamlined set of snippets to handle the notch with iPhone X phones, based on this article from CSS Tricks.
Enable in header.php
:
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
Add this snippet as a mixin in assets/scss/mixins/_sugar.scss
// iPhoneX
@mixin iPhoneX() {
padding: 0 env(safe-area-inset-right) 0 env(safe-area-inset-left);
}
To use this, make sure there is a containing element around .container
elements. This outer element will hold any section background images, colors, etc. and gets the mixin applied to it, which will stretch those to the edges of the screen.
<?php
/*
* Hero (global)
*
* Template part used on various templates/views
*
* @package F1 Project Name
* @author Factor1 Studios
* @since 0.0.1
*/
// Hero Custom Fields
$img = wp_get_attachment_image_src(get_post_thumbnail_id(), 'hero');
$headline = get_field('hero_headline'); ?>
<section class="hero" style="background: url('<?php echo $img[0]; ?>') center/cover no-repeat">
<div class="container">
<div class="row">
<div class="col-12">
<h1><?php echo $headline; ?></h1>
</div>
</div>
</div>
</section>
/*
* Hero (home)
*
* Template part used on the home template
*
* @package F1 Project Name
* @author Factor1 Studios
* @since 0.0.1
*/
.hero--home {
position: relative;
@include iPhoneX;
overflow: hidden;
.container {
padding: rem(270) 0 rem(250);
z-index: 1;
}
&:after {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: linear-gradient(to bottom, rgba(0, 0, 0, .9), rgba(0, 0, 0, 0) 35%);
}
}
// Media Queries
@media screen and (max-width: $small-breakpoint) {
.hero--home .container {
padding: rem(170) 0 rem(210);
}
}
Unless told otherwise, always include “Site by factor1” in the footer.
<p>Site by <a href="https://factor1studios.com" class="factor1">factor1</a></p>
.factor1 {
font: 700 rem(14)/1 'Helvetica', sans-serif;
letter-spacing: -.1em;
color: $white;
&:hover {
color: $buff;
}
}
Add these snippets to your PHP & JS functions to make use of WooCommerce's built-in quantity parameter:
PHP Function (adds this as a shortcode option)
function custom_add_to_cart( $atts = array(), $content = null ) {
$id = get_the_ID();
$form = '
<form class="custom-add-to-cart">
<input type="number" name="quantity" id="quantity" min="0" max="100" step="1" value="1" />
<input type="hidden" value="' . $id . '" name="product_id" id="product_id" />
<input type="hidden" value="' . esc_url(wc_get_cart_url()) . '" name="cart" id="cart" />
<button type="submit" class="button--primary">Add to Cart</button>
</form>
';
return $form;
}
add_shortcode('custom_add_to_cart', 'custom_add_to_cart');
JS 'Redirect' (requires DOMPurify: yarn add dompurify
)
import * as DOMPurify from 'dompurify';
...
// Pass variable to query string
$("form.custom-add-to-cart").on("submit", function(e) {
e.preventDefault();
let data = $(this).find(":input"),
qty = DOMPurify.sanitize(data[0].value),
product = DOMPurify.sanitize(data[1].value),
cart = DOMPurify.sanitize(data[2].value);
let newUrl = `${cart}?add-to-cart=${product}&quantity=${qty}`;
window.location.href = newUrl;
});
Here's some other common functions to add in as needed.
// Slugify strings
function slugify($str, $delimiter = '-'){
$slug = strtolower(trim(preg_replace('/[\s-]+/', $delimiter, preg_replace('/[^A-Za-z0-9-]+/', $delimiter, preg_replace('/[&]/', 'and', preg_replace('/[\']/', '', iconv('UTF-8', 'ASCII//TRANSLIT', $str))))), $delimiter));
return $slug;
}
// Custom Excerpt Length
function custom_excerpt_length( $length ) {
return 20;
}
add_filter( 'excerpt_length', 'custom_excerpt_length', 999 );
// Adjust queries
function adjust_queries($query) {
// Blog
if( !is_admin() && (is_home() || is_category() || is_tag() || is_search() ) && $query->is_main_query() ) {
$featured = get_field('blog_featured_post', get_option('page_for_posts'))->ID;
if( $featured ) {
$query->set('post__not_in', array($featured));
}
}
}
add_action('pre_get_posts', 'adjust_queries');
Feel free to open an issue if you find mistakes, enhancements, or would like to see some new documentation.