Developers all share the experience of almost remembering some code they saw on Stackoverflow or blog post once. Sometimes even convincing themselves that it was used in another once of their projects (it wasn't). Scouring their search history for hours to no avail, only to be left in utter despair. Their once hot drink now sitting cold, undrinkable and staring at you... shaming you. That's happened to me far too many times and in a moment of strength I thought (extremely) loudly "THIS SHALL HAPPEN NO MORE!". So, I decided that I'll collate all of the ones I come back to again and again.
Taken from the infamous CSS Tricks post A Complete Guide to Grid. This serves as a good starting point for setting up your responsive grid.
.grid {display: grid;grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));/* This is better for small screens, once min() is better supported *//* grid-template-columns: repeat(auto-fill, minmax(min(200px, 100%), 1fr)); */grid-gap: 1rem;/* This is the standardized property now, but has slightly less support *//* gap: 1rem */}
A useful snippet when you need to break out of some constraints in the page layout e.g a grid of images between some written content that fills the width of the page.
.full-width {width: 100vw;position: relative;left: 50%;right: 50%;margin-left: -50vw;margin-right: -50vw;}
Too much uniformity in a layout can create for a sub par experience, to create some moments of interest you can break out slightly, but not full width.
.not-full-but-bigger {margin: auto calc(50% - 50vw);width: 60vw;transform: translateX(calc(50vw - 50%));}
An essential snippet of code to have in your arsenal. No more CSS hacks or over engineered Javascript solutions needed.
.line-clamp {display: -webkit-box;-webkit-line-clamp: 3;-webkit-box-orient: vertical;overflow: hidden;}
A CSS only carousel, made possible by the introduction of scroll-snap. If you're wanting chevrons and click to slide functionality stick to a JS library, but for a mobile only carousel it works great.
.carousel {display: flex;width: 100%;overflow-x: auto;scroll-snap-type: x mandatory;}.carousel .item {flex-shrink: 0;width: 100%;scroll-snap-align: center;}/* hide horizontal scroll bar Chrome/Safari */.carousel::-webkit-scrollbar-track,.carousel::-webkit-scrollbar,.carousel::-webkit-scrollbar-thumb {width: 0 !important;}.carousel {/* Firefox */scrollbar-width: none;/* IE */ms-overflow-style: none;}
Sometimes it can be a pain remembering the order of each background property (it gets me every time).
/* image, position, size and repeat */body {background: url(sweettexture.jpg) top center / 200px 200px no-repeat;}
Remember that the icon/image is declared after the colour. A good use case for this is image placeholders, for example you could have your companys logo above their brand grey.
.image-placeholder {background: #eff0f2 url('./icons/logo.svg');}/* alternatively we can define colour and image seperately for the same effect */.image-placeholder {background-color: #eff0f2;background-image: url('./icons/logo.svg');}
Although improving, underlining text in CSS doesn't allow for many stylistic customisations (like stroke width or space from the text). The below solution creates a flexible underline which skips any descenders.
li {// for the underline to "skip" the descenderstext-shadow: 1px 1px var(--primary-background), 1px -1px var(--primary-background),-1px 1px var(--primary-background), -1px -1px var(--primary-background);}.current-menu-item {position: relative;&:before {content: '';position: absolute;left: 0;right: 0;height: 1.5px;bottom: 1px;background: var(--primary-foreground);z-index: -1;}}
To make buttons more accessible we need to let screen readers differentiate each buttons intention. By utilising the visually-hidden
class name we can hide the text (keeping only the icon) and out buttons will be accessible.
.visually-hidden {position: absolute;overflow: hidden;clip: rect(0 0 0 0);height: 1px;width: 1px;margin: -1px;padding: 0;border: 0;}
Say we have created a link with text-decoration: none
and we want the underline to show on hover, instead of explicitly saying text-decoration: underline
we can use revert
so it falls back to the original "state".
a {text-decoration: none;&:hover {text-decoration: revert;}}
This is a fairly tricky thing to understand because we normally understand css as only being able to look inward. However, with Styled components we can check whether a styled component exists within another component and change those styles accordingly.
const TextLink = styled.a`/* Standard styles: */color: blue;text-decoration: none;/* Styles when rendered inside a quote: */${QuoteContent} & {color: black;text-decoration: revert;}`;
Taken from Josh Comeau's course css-for-js devs
Utilising the "Lobotomised Owls" selector we can create more consistent spacing between elements on our pages. Essentially we are telling the browser to only apply margin top to those elements which have a previous sibling.
.stack {--space: 1.5rem;display: flex;flex-direction: column;justify-content: flex-start;}.stack > * {margin-top: 0;margin-bottom: 0;}.stack > * + * {margin-top: var(--space);}
references:
For context about the code: Every Layout - The Stack
To learn about the origins: Axiomatic CSS and Lobotomized Owls
Prevent the pesky issue where the nested navigation disappears before we can get to it! No need for any JS, take advantage of transition-delay. Taken from Josh Comeau’s CSS for JS developers course.
.dropdown {opacity: 0;transition: opacity 400ms;transition-delay: 300ms;}.dropdown-wrapper:hover .dropdown {opacity: 1;transition: opacity 100ms;transition-delay: 0ms;}
I've always used forwards in the past because I never thought to explore the other options. As it turns out there is a both
option, which means no more adding default styles before the keyframes animation!
.box {animation: slide-in 1000ms ease-out both;animation-delay: 500ms;}
When you have merged and deleted a branch on github this command will delete the local branches that dont exist remotely.
git branch -vv | grep 'origin/.*: gone]' | awk '{print $1}' | xargs git branch -d
Refreshes the tracking of your files. Super useful for adding new things to your .gitignore file.
git rm -r --cached .
An underrated command in my opinion. Need to quickly switch branch to do something but don't want to commit your changes on the current branch just yet? Git stash is perfect for this.
# for when it's too hard to think of a messagegit stash# to make it clearer what each stash isgit stash save "optional message for yourself"# apply the latest stash (I tend to use this the most)git stash apply stash@{0}# view a list of your stashesgit stash list
var { src, dest, series, watch } = require('gulp');var browserSync = require('browser-sync').create();var sass = require('gulp-sass');const rename = require('gulp-rename');let scss = () => {return src('./sass/main.scss').pipe(sass()).pipe(rename('style.css')).pipe(dest('./', { overwrite: true }));};let editorStyles = () => {return src('./sass/editor.scss').pipe(sass()).pipe(rename('gutenberg-editor-styles.css')).pipe(dest('./styles', { overwrite: true }));};let server = () => {return browserSync.init({proxy: '<http://localhost:8888>',});};let reload = (done) => {browserSync.reload();done();};watch(['**/*.scss'], series(scss, editorStyles, reload));watch(['**/*.js', '**/*.php'], reload);exports.scss = scss;exports.server = server;exports.default = series(scss, editorStyles, server);
An HTML first "accordian". Forget about using Javascript and make it simple for yourself by utilising semantic HTML. You can also style the default arrow by targeting the :marker
pseudo element.
<details><summary>What?</summary>Stay Home Stay Safe!</details>
<ahref="<https://twitter.com/CollierAdam>"target="_blank"rel="noopener noreferrer">DM me on Twitter.</a>
Because sometime you just need to chunk some stuff.
const chunk = (arr, size) =>Array.from({ length: Math.ceil(arr.length / size) }, (v, i) =>arr.slice(i * size, i * size + size));
An interesting snippet I came across on The Cost of Javascript. I'll be using this trick the next time I'm parsing big chunks of JSON.
const data = { foo: 42, bar: 1337 }; // 🐌const data = JSON.parse('{"foo":42,"bar":1337}'); // 🚀
Intoduced in ES6 we can now easily flatten multi dimensional arrays. Gone are the days of having to create our own solution (taken from stackoverflow).
// This method accepts one argument to choose the depth of the flatteningconst multiDimensionalArray = [[1, 2],[3, 4],[5, 6],];const flattenedArray = multiDimensionalArray.flat(); // [1, 2, 3, 4, 5, 6]
A pretty neat solution, by leveraging ES6 Object destructuring assignment we can immutably remove properties.
const item = {id: 1,price: 50,image: 'item.jpeg',};const { id, ...item2 } = item;// now item 2 doesnt have an id propertyconsole.log(item2);
More than anything it's going to save you some heaps of typing, it's a neat solution for something that has plagued developers sanity for many a year.
// Instead of something likeconst city = user && user.address && user.address.city;// We can doconst city = user?.address?.city;
No other excuse, I just forget what this is all the time.
document.addEventListener('DOMContentLoaded', function () {// Handler when the DOM is fully loaded});
Simple, elegant and it will save you a bunch of time. No more mapping or filtering involved.
myArray.find((x) => x.id === '45').author;
// Child elements are usually a HTMLCollection (which we can't map over)// So we need to convert it to an array firstArray.from(element.children).map((child) => {// by setting to true we grab the whole subtree toolet clonedChild = child.cloneNode(true);element.appendChild(clonedChild);});
Sometimes when using API's or text from the document special characters are encoded into HTML entities. We can take advantage of the textarea
tag to auto decode these strings for us.
export const decodeHtmlEntities = (html) => {var textArea = document.createElement('textarea');textArea.innerHTML = html;let decodedHTML = textArea.value;textArea.remove();return decodedHTML;};
Find all of the Node module directories, check how big each one is and the total amount of space it takes up (it can be a surprising amount of space)
find . -name "node_modules" -type d -prune -print | xargs du -chs
Delete all of your node modules from your mac and sit there, shocked at the number of modules you've just erased.
find . -name 'node_modules' -type d -prune -print -exec rm -rf '{}' \\;
taken from Go Make Things
npx npm-check -u
Yalc is a great little tool similar to the likes of yarn link and npm link. What it allows us to do is use our local component packages as dependencies of other projects. I prefer Yalc because it physically changes your package.json so you are always aware of which component package you're using and where from.
Install Yalc globally:
# install globallynpm i -g yalc# publish package locallyyalc publish# publish and update all projects using that yalc storeyalc publish --push# add your local package as a dependencyyalc add my-package# (This will change/add the package location in your package.json)# remove it from / revert your package.jsonyalc remove my-package
NVM (Node Version Manager) is a tool which helps you easily manage your Node versions. Without NVM managing node versions locally is a real pain, install this once and breathe a sigh of relief.
Your Node install looking a little outdated? easily install the latest stable version of node.
nvm install node
Check what versions of Node you have installed, if you have a new one installed you can switch it there and then
nvm list
If you need to use a specific version of Node for a project declare it in the command.
nvm install 6.14.4 # or 10.10.0, 8.9.1, etc
Are new terminal sessions using different versions of Node? Set your default version which will be used across everything.
nvm alias default node
The Oh My ZSH framework for managing your ZSH configuration and comes bundled with thousands of helpful functions, plugins and themes. It's a real game changer.
Taken from the github README.
sh -c "$(curl -fsSL <https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh>)"
This is the theme that I use because it's super simple and as customisable as you want. Personally I like it for it's unobtrusive design.
# lets cd into our custom themes directorycd ~/.oh-my-zsh/custom/themes# clone the themegit clone <https://github.com/geometry-zsh/geometry>
To activate the theme in your .zshrc file:
ZSH_THEME="geometry/geometry"
Oh My ZSH can be a real time by utilising the community driven plugin ecosystem. A few of the plugins I like to use:
To add these plugins to your Oh My ZSH install:
# let's cd into our custom plugins directorycd ~/.oh-my-zsh/custom/plugins# clone the zsh-syntax-highlighting plugingit clone <https://github.com/zsh-users/zsh-syntax-highlighting.git> ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-syntax-highlighting# clone the zsh-nvm plugingit clone <https://github.com/lukechilds/zsh-nvm> ~/.oh-my-zsh/custom/plugins/zsh-nvm# clone the zsh-autosuggestions plugingit clone <https://github.com/zsh-users/zsh-autosuggestions> ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-autosuggestions
then in our .zshrc file lets initialise the plugins
plugins=(gitzsh-syntax-highlightingzsh-autosuggestionszsh-nvm)
Annoyingly there is a percentage sign issue in Hyper, here's how to fix it. Let's add the below to the bottom of our .zshrc file.
# prevent percentage prompt when first openunsetopt PROMPT_SP
It's always a nice touch to have your personal terminal title showing.
cd ~/.oh-my-zsh/custom/themes/geometry# open vs codecode .# find this line in geomatry.zshgeometry::clear_title() { print -n '\\e]0;%~\\a'; }# and amend togeometry::clear_title() { print -n "\\e]0;Adam's Terminal\\a"; }
A nice easy way to grab icons anywhere in your site.
<?php include("icons/my-icon.svg"); ?>// getting an icon from a parent directory<?php include __DIR__ . '/../icons/facebook.svg'; ?>
A method to functionally add scripts to your wordpress projects footer.
wp_enqueue_script('lazysizes',get_template_directory_uri() . '/js/lazysizes.min.js');
Reuse some templated PHP content you have created
<?php get_template_part('template_parts/griditem'); ?>
Sometimes you need to pass variables down into a template part, a similar thinking pattern to react and props.
// you can use any value including objects.set_query_var( 'var_name_to_be_used_later', 'Value to be retrieved later' );// in the template part$passedVariable = get_query_var('var_name_to_be_used_later');
If you have ever done any Gutenberg block development for Wordpress this is an essential snippet.
// lets grab all of the blocks from the post content$blocks = parse_blocks($post->post_content);// and lets print it outvar_dump($blocks);
Taken from @kentcdodds great blog post How to use React Context effectively. A good base for setting up global state in any React application.
// context.jsimport React from 'react';const StateContext = React.createContext();const DispatchContext = React.createContext();// handle the reducerconst stateReducer = (state, action) => {switch (action.type) {// an example actioncase 'increment': {return { count: state.count + 1 };}default: {throw new Error(`Unhandled action type: ${action.type}`);}}};const initialState = {count: 0,};function StateProvider({ children }) {const [state, dispatch] = React.useReducer(stateReducer, initialState);return (<StateContext.Provider value={state}><DispatchContext.Provider value={dispatch}>{children}</DispatchContext.Provider></StateContext.Provider>);}function useAppState() {const context = React.useContext(StateContext);if (context === undefined) {throw new Error('useAppState must be used within a StateProvider');}return context;}function useAppDispatch() {const context = React.useContext(DispatchContext);if (context === undefined) {throw new Error('useAppDispatch must be used within a StateProvider');}return context;}function useContext() {return [useAppState(), useAppDispatch()];}export { StateProvider, useContext };
// Any react fileimport { useContext } from "../../context"// use destructuring to make state and dispatch accessible// count in this case is destructured from the stateconst [{ count }, dispatch] = useContext()// you could just doconst [state, dispatch] = useContext()// then we can dispatchdispatch({ type: "count" })// or use the state<div>{count}</div>
React in general tends to frown upon mutating values, especially when updating state. So here are a few methods I like to use to update immutably. Many more can be found in Redux's post Immutable Update Patterns
The spread operator comes into it's essense here, making it easy to update an object.
// state = {// clicks: 0,// count: 0// }return {...state,clicks: state.clicks + 1,count: state.count - 1,};
We can spread the current array values to the beginning of our new array, followed by our extra value.
const newItem = 'foo';// a new arrayreturn [...state, // explode the old state firstnewItem, // then add the new item at the end];
Taking advantage of ES6 spread operators we can add an item to an array immutably.
const newItem = 'foo';// a new arrayreturn [newItem, // add the new item first...state, // then explode the old state at the end];
Map is perfect for returning a new array, in this case we can update an item by index.
return state.map((item, index) => {// Replace the item at index 2if (index === 2) {return 3;}// Leave every other item unchangedreturn item;});
Conditionally render components based on the browser size rather than rendering and hiding the components with CSS. Taken from @cassidoo's post Building a custom React media query hook for more responsive apps
import { useState, useEffect } from 'react';export function useMediaQuery(query) {const [matches, setMatches] = useState(false);useEffect(() => {const media = window.matchMedia(query);if (media.matches !== matches) {setMatches(media.matches);}const listener = () => {setMatches(media.matches);};media.addListener(listener);return () => media.removeListener(listener);}, [matches, query]);return matches;}// how to use itfunction Page() {let isPageWide = useMediaQuery('(min-width: 800px)');return (<>{isPageWide && <UnnecessarySidebar />}<ImportantContent /></>);}
A very basic example of how we can pass props down to props.children. If you're wanting to abstract away some logic, make your code more readable or make it easy to switch out components, this is a great solution.
// inside our component we add the props we want as arguments for props.childrenconst Blocks = ({ allBlocks, children }) =>allBlocks.map((block, index) => <div>{children(block, index)}</div>);// then we can access those arguments via a function<Blocks allBlocks={state.allBlocks}>{(block, index) => {return <DynamicBlock block={block} index={index} />;}}</Blocks>;
Very common to find in Github README's the tree command makes it super easy to get directory structures in an easy to read format.
# Get the tree of the first directory leveltree -v -L 1# Ignore node_modules and grab the tree two directory levels downtree -I 'node_modules' -v -L 2
Wordpress's officially documentation is pretty good for this. (I do wish there was a quick and easy CLI solution for this).
Go to MAMP > Preferences > Ports
and set Apache Port to be 80
Open the hosts file in VS Code:
cd /etccode hosts
Add the urls you want to use:
127.0.0.1 your-site.test
(you may need to sudo save, VS Code makes this easy for you)
Add the virtual hosts to the end of /Applications/MAMP/conf/apache/extra/httpd-vhosts.conf
:
<VirtualHost *:80>DocumentRoot "/Applications/MAMP/htdocs" ServerName localhost</VirtualHost><VirtualHost *:80>ServerName your-site.test DocumentRoot "/Users/username/Sites/directory"</VirtualHost>
(notice how we are re-setting up the main localhost first)
And make sure the NameVirtualHost is set to:
NameVirtualHost *:80
Then in /Applications/MAMP/conf/apache/httpd.conf
Uncomment this line:
# Include /Applications/MAMP/conf/apache/extra/httpd-vhosts.conf
Find this line:
<Directory />Options Indexes FollowSymLinksAllowOverride None</Directory>
and change it from None
to All
:
Lastly find these two instances:
Listen 8888ServerName localhost:8888
and change them to:
Listen 80ServerName localhost:80
and then it should work!
If you find your site feels a little sluggish compared to using localhost you can speed up the lookup time by adding it as an alias. So in /etc/hosts
:
127.0.0.1 localhost your-site.test
When switching to virtual hosts from a localhost setup the site address and wordpress address general settings were causing some issues. You may find you can't access the admin, because its setup for a different url, so here's how to fix that.
Open your projects wp-config.php
file and after the “define” statements (just before the comment line that says “That’s all, stop editing!”), insert a new line:
define('RELOCATE',true)
Now if your site is at http://www.yourdomainname.com
your need to go to http://www.yourdomainname.com/wp-login.php
(notice how we are manually accessing the wp-login.php file)
Login in as normal and make the changes in General > Settings
Make sure to remove define('RELOCATE',true)
after successfully changing the urls.
Do you know a great snippet which you think should be added to this page? Send it over and I'll take a look!
Table of Contents
Like the content I'm creating? Show some love and:
Buy me a Coffee