We’ve talked quite a bit about project management and workflows around here at CSS-Tricks, not because it’s the core of what we do as designers and developers, but because we all play a role in it as part of a team and because it impacts the quality of our work at the end of the day.
That’s why having a good system in place is such a benefit both to us and to teams as a whole. Where can you find a system like that? You might want to start by looking at monday.com. Yes, it’s a project management tool but it actually goes way beyond that. Where some other platforms out there stop at task lists, calendars, and milestones, monday.com does those plus team collaboration.
If you’ve ever felt out of the loop on a project, had a surprise change in scope, or even been curious what other folks on your team have been up to, that’s where monday.com really shines. It’s people-centric, giving you and others insight into activity across an entire project through news feeds, messaging, shared assets, clearly defined user roles, among any other things. It’s what a healthy, transparent, and collaborative team environment looks like.
We’ve only scratched the surface here, but lucky for you, there’s a free 14-day trial to check out everything that monday.com has to offer. Go for it!
One way to deal with long, complex forms is to break them up into multiple steps. You know, answer one set of questions, move on to another, then maybe another, and so on and so forth. We often refer to these as multi-step forms (for obvious reasons), but others also take to calling it a “wizard” form.
Multi-step forms can be a great idea! By only showing a few inputs on a screen at a time, the form may feel more digestible and prevent users from feeling overwhelmed by a sea of form fields. Although I haven’t looked it up, I’m willing to say no one enjoys completing a ginormous form — that’s where multiple steps can come in handy.
The problem is that multi-step forms — while reducing perceived complexity on the front end — can feel complex and overwhelming to develop. But, I’m here to tell you that it’s not only achievable, but relatively straightforward using React as the base. So, that’s what we’re going to build together today!
The easiest way to create a multi-step form is to create a container form element that contains all the steps inside of it as components. Here’s a visual showing that container (<MasterForm/>), the components inside of it (<Step1/>, <Step2/>, <Step3/>) and the way states and props are passed between them.
<MasterForm/> serves as the container while three child components inside of it act as each step of the form.
Although it seems to be more complex than a regular form, a multi-step form still uses the same principles as a React form:
State is used for storing data and user inputs.
Component is used for writing methods and the interface.
Props are used for passing data and function into elements.
Instead of having one form component, we will have one parent component and three child components. In the diagram above, <MasterForm/> will send data and functions to the child components via props, and in turn, the child components will trigger a handleChange() function to set values in the state of <MasterForm/>. It’s one big happy family over here!
We’ll need a function to move the form from one step to another as well, and we’ll get to that a little later.
The step child (get it?) components will receive props from the <MasterForm/> parent component for value and onChange props.
<Step1/> component will render an email address input
<Step2/> will render a username input
<Step3/> will render a password input and a submit button
<MasterForm/> will supply both data and function into child components, and child components will pass user inputs back to the parent using its props.
Creating the step (child) components
First, we’ll create the form’s child components. We’re keeping things pretty barebones for this example by only using one input per step, but each step could really be as complex as we’d like. Since the child components look almost similar between one another, I’m just gonna show one of them here. But be sure to take a look at the demo for the full code.
class Step1 extends React.Component {
render() {
if (this.props.currentStep !== 1) { // Prop: The current step
return null
}
// The markup for the Step 1 UI
return(
<div className="form-group">
<label htmlFor="email">Email address</label>
<input
className="form-control"
id="email"
name="email"
type="text"
placeholder="Enter email"
value={this.props.email} // Prop: The email input data
onChange={this.props.handleChange} // Prop: Puts data into state
/>
</div>
)
}
}
Now we can put this child component into the form’s render() function and pass in the necessary props. Just like in React’s form documentation, we can still use handleChange() to put the user’s submitted data into state with setState(). A handleSubmit() function will run on form submit.
Next up, the parent component
Let’s make the parent component — which we’re all aware by now, we’re calling <MasterForm/> — and initialize its state and methods.
We’re using a currentStep state that will be initialized with a default value of 1, indicating the first step (<Step1/>) of the form. We’ll update the state as the form progresses to indicate the current step.
class MasterForm extends Component {
constructor(props) {
super(props)
// Set the initial input values
this.state = {
currentStep: 1, // Default is Step 1
email: '',
username: '',
password: '',
}
// Bind the submission to handleChange()
this.handleChange = this.handleChange.bind(this)
}
// Use the submitted data to set the state
handleChange(event) {
const {name, value} = event.target
this.setState({
[name]: value
})
}
// Trigger an alert on form submission
handleSubmit = (event) => {
event.preventDefault()
const { email, username, password } = this.state
alert(`Your registration detail: \n
Email: ${email} \n
Username: ${username} \n
Password: ${password}`)
}
// Render UI will go here...
}
OK, that’s the baseline functionality we’re looking for. Next, we want to create the shell UI for the actual form add call the child components in it, including the required state props that will be passed from <MasterForm/> via handleChange().
render() {
return (
<React.Fragment>
<h1>A Wizard Form!</h1>
<p>Step {this.state.currentStep} </p>
<form onSubmit={this.handleSubmit}>
// Render the form steps and pass in the required props
<Step1
currentStep={this.state.currentStep}
handleChange={this.handleChange}
email={this.state.email}
/>
<Step2
currentStep={this.state.currentStep}
handleChange={this.handleChange}
username={this.state.username}
/>
<Step3
currentStep={this.state.currentStep}
handleChange={this.handleChange}
password={this.state.password}
/>
</form>
</React.Fragment>
)
}
One step at a time
So far, we’ve allowed users to fill the form fields, but we’ve provided no actual way to proceed to the next step or head back to the previous one. That calls for next and previous functions that check if the current step has a previous or next step; and if it does, push the currentStep prop up or down accordingly.
class MasterForm extends Component {
constructor(props) {
super(props)
// Bind new functions for next and previous
this._next = this._next.bind(this)
this._prev = this._prev.bind(this)
}
// Test current step with ternary
// _next and _previous functions will be called on button click
_next() {
let currentStep = this.state.currentStep
// If the current step is 1 or 2, then add one on "next" button click
currentStep = currentStep >= 2? 3: currentStep + 1
this.setState({
currentStep: currentStep
})
}
_prev() {
let currentStep = this.state.currentStep
// If the current step is 2 or 3, then subtract one on "previous" button click
currentStep = currentStep <= 1? 1: currentStep - 1
this.setState({
currentStep: currentStep
})
}
}
We’ll use a get function that will check whether the current step is 1 or 3. This is because we have three-step form. Of course, we can change these checks as more steps are added to the form. We also want to display the next and previous buttons only if there actually are next and previous steps to navigate to, respectively.
// The "next" and "previous" button functions
get previousButton(){
let currentStep = this.state.currentStep;
// If the current step is not 1, then render the "previous" button
if(currentStep !==1){
return (
<button
className="btn btn-secondary"
type="button" onClick={this._prev}>
Previous
</button>
)
}
// ...else return nothing
return null;
}
get nextButton(){
let currentStep = this.state.currentStep;
// If the current step is not 3, then render the "next" button
if(currentStep <3){
return (
<button
className="btn btn-primary float-right"
type="button" onClick={this._next}>
Next
</button>
)
}
// ...else render nothing
return null;
}
All that’s left is to render those buttons:
// Render "next" and "previous" buttons
render(){
return(
<form onSubmit={this.handleSubmit}>
{/*
... other codes
*/}
{this.previousButton}
{this.nextButton}
</form>
)
}
Congrats, you’re a form wizard! 🧙
That was the last step in this multi-step tutorial on multi-step forms. Whoa, how meta! While we didn’t go deep into styling, hopefully this gives you a solid overview of how to go about making complex forms less… complex!
Here’s that final demo again so you can see all the code in it’s full and glorious context:
React was made for this sort of thing considering it makes use of states, property changes, reusable components and such. I know that React may seem like a high barrier to entry for some folks, but I’ve written a book that makes it a much lower hurdle. I hope you check it out!
You know about the State of JavaScript survey, where thousands upon thousands of developers were surveyed about all-things-JS, from frameworks to testing and many other things in between? Well, Sacha Greif has launched one focused entirely on CSS.
This is super timely given a lot of the content we and other sites have been posting lately centered around learning, complexity, changing roles, and more. Sacha captures it nicely:
This is especially interesting since it comes at a time where many are talking about a “Great Divide” between the “front” of the front-end (HTML, CSS) and the “back” of the front-end (JavaScript and its many frameworks and libraries). […] [T]he survey will be a great chance to take a snapshot of the community as it currently exists, and see how this evolves over the next couple years.
Sounds like a good goal. Let’s help by putting some responses in there!
I’ll be there in Seattle for the kickoff, giving a talk about how to think like a front-end developer. I’ve been working on it for ages, and I think I have a talk ready that helps set the stage for where we are at in the world of front-end development, through the lens of tons of other front-end developers I admire in this industry. I hope it’ll be an entertaining romp through all their minds and how they think.
Just check out this Seattle lineup!
This is like my dream lineup. Except that jerk who kicks off Day 2.
Jeffrey Zeldman The Zen of Whitespace: Slow Design for an Anxious World
Margot Bloomstein Designing for Slow Experiences
Sarah Parmenter Designing for Personalities
Eric Meyer Generation Style
Rachel Andrew Making Things Better: Redefining the Technical Possibilities of CSS
Jen Simmons Designing Intrinsic Layouts
Chris Coyier (me!!!) How to Think Like a Front-End Developer
Una Kravets From Ideation to Iteration: Design Thinking for Work and for Life
Scott Jehl Move Fast and Don’t Break Things
Luke Wroblewski Mobile Planet
Beth Dean Unsolved Problems
Dan Mall Putting the ‘Design’ in Design Systems
Jeremy Keith Going Offline
Sarah Drasner Animation on the Bleeding Edge
Val Head Making Motion Inclusive
Derek Featherstone Inclusive, by Design
Gerry McGovern The Customer-Obsessed Professional
Another neat little feature of the 2019 lineup is a screening of the documentary Rams that after lunch on Day 2. Like movie night. For us designer types. During the day. It’s gonna be awesome.
The topic of how accessible it is for newbies and seasoned developers alike to learn CSS has been gaining steam as the complexity of the tools around it has become skewed more toward traditional programming. Rachel Andrew has much more to say about this in her post, HTML, CSS and our vanishing industry entry points. Robin also has thoughts on where and how to learn CSS in the modern age.
The question of how and where to learn CSS is a highly reasonable thing to ask. The answer depends on all sorts of things: how serious you are, your current foundation, what other resources are available to you, what you hope to do with what you learn, and how much time you have, among probably a zillion other things.
Let me dump a bunch of possible answers here and you can apply all those “well, that depends” caveats as you see fit.
There are a ton of books out there that cover HTML and CSS (and often together). They probably all do a fine job. There’s no need to chronicle all the choices here. These two are my personal recommendations. You probably don’t even need both.
Jon Duckett’s is incredibly well-designed and approachable:
Jennifer Robbins’ covers a bit more ground and is designed to be useful for either personal reading or classroom learning.
You could read through all the posts in our Beginner’s Guide.
We have a guide (a collection of articles, videos, and links) called Just Starting Out with CSS & HTML. I hope there is stuff in there that can help kickstart or augment your early learning because that’s the intent.
You could go through other free online guides.
freeCodeCamp is probably the biggest and best out there. Definitely check them out.
We designed HTML & CSS Is Hard to be the only introduction to HTML and CSS that you’ll ever need. If you put in the effort to read every section and write every code snippet, this tutorial has the potential to replace hundreds or even thousand of dollars worth of online courses and live training.
Prefer video? Jessica Hische and Russ Maschmeyer’s Don’t Fear the Internet is a super eight-part series that gets you going with HTML & CSS — it even delves into the all-important topic of typography.
Khan Academy has an Intro to HTML/CSS: Making webpages course that’s packaged in a super cool format. It’s like video in that you get to hear the instructor talk you through the learning, but what you see is a real live text editor and real live output. Sometimes the teacher is controlling the code, and then sometimes it breaks for challenges in which you take over and edit the code yourself.
Eric Tirado has an Intro to HTML course on Scrimba, which is also a neat platform in that Eric’s voice guides you through the course, but visually it’s a combination of slides with a real code editor and preview.
You could find and take a paid online course.
I often join gyms because the accountability of paying for something gets me to do it. I know I can do situps, pushups, and go for a jog for free, but the gym membership makes a thing of it. Well, same could be said about paying for a course on HTML and CSS.
These are broad generalizations, but good places to start:
If you wanna put even more skin in the game, you could consider literally going to school. If you don’t have a college degree, that’s an option, although you’ll be looking at a broad education rather than a ticket to leveling up your web design and development skills alone. I’m a fan of that just for the general mind-broadening it involves.
But assuming you’re going to go to a coding-specific school…
There are options that exist in single cities. I know someone who went to the All-Woman’s coding bootcamp Hackbright in San Francisco. There are places like Actualize in Chicago, Center Centre in Tennessee, and HackerYou in Toronto.
There are bigger outfits like, Flatiron school (with campuses all around the U.S.) and General Assembly (with campuses all around the world).
There are probably dozens — if not hundreds — more, so this is more to inform you of the possibility of schooling. You don’t even have to go to a physical school since plenty of these offer online courses, too (but with the advantage of live instruction and cohorts). For example, LambdaSchool has the novelty of being free to start and paid later in the form of letting them take a portion of your salary after you get a job in the industry.
You could practice on CodePen.
Not every second of your learning should be strictly following some course laid out by a book, class, or teacher. It wouldn’t even be that way if you tried. You might as well embrace that. If something tickles your muse, go play! I hope CodePen is a rewarding place to do that, making it both easy and useful, while providing a place to connect with other folks in the field.
You could build a personal site and learn what you need to get it done.
That’s how absolutely countless developers have cut their teeth, including me. I wanted a personal website years ago, and I struggled through getting a self-hosted WordPress site online so I could have full control over everything and bend it to my will. Once you have an actual website online, and you know at least some people are seeing it, it gives you all the motivation in the world to keep going and evolve further.
The way you actually learn is going to be a combination of all this stuff.
People are obsessed with asking musicians if they’re self-taught. Like, if they are, their amazingness triples because it means their creative genius was delivered by a lightning bolt at birth. They don’t need anyone else to learn; they merely look at those guitar strings and know what to do.
And if they were taught by a teacher, then, well, that’s all out the door. If they are good at all, then it’s because the teacher delivered that to them.
Total nonsense.
People learn anything — music and web development included — inside a hurricane of influences. Let’s stick with music for a second. Learning to play comes in many forms. You learn by listening to music an awful lot. You can do fundamental practice, like finger exercises and going up and down scales. You can learn to transpose chords on a chalkboard. You can watch YouTube all day and night. You can sign up for online courses. You can go to local jams to watch and play along. You can join a band. You can take lessons from someone advertising on Craigslist. You can go to a local music school. You can read books about music.
You get the idea.
You can and probably will do all of that. With learning web design and development, getting anywhere will involve all sorts of ways. There’s no silver bullet. It takes bashing on it lots of different ways. There’s no requirement to sprinkle money on it, but you do need multiple angles, time, and motivation.
Howdy folks! 🎉 I’m Simon Owen, and over the years, I’ve loved being a part of and learning from the dotfiles community. I spend a lot of time teaching developers and running workshops. In those sessions, demonstrating how I set up my development environment is often one of things that folks appreciated the most.
Dotfiles are a key part of my development environment. Haven’t heard of them? Well, even if you have, it’s a good idea to walk through what they are and the benefits of using them.
If you’re hearing about dotfiles for the first time, it’s totally fine to be confused about what they are and what they do. I recall that it took me a considerable amount of time before I realized a dotfile is simply a file that has a dot in front of the file name!
There are two common examples of dotfiles. First, the ones you might already be familiar with are those often found at the root of many open source projects — for example, .editorconfig contains code editor preferences to help maintain consistent coding styles for a project. You may also have seen .stylelintrc and .eslintrc floating around, which set CSS and JavaScript rules, respectively.
Second (and the ones we’re looking at today), are dotfiles that can live at the root level of a user directory (i.e. /Users/<username> ). One such dotfile is .aliases, which contains custom named commands that can speed up work in the Terminal. Another is .bash_prompt, which is used to change the $ in Terminal to something a little more fun. In my case, I set it so this dude pops up to make me smile when things get tough:
༼ つ ◕_◕ ༽つ
Hopefully, you’re already starting to get a good sense of how useful dotfiles can be. They’re sort of like hidden gems (literally, since they’re hidden from views by default) that unlock superpowers for your machine to help with development. We’re talking about automation, optimizations, and efficient workflows, among other things.
First, I want to give props to the dotfiles community
Before we dig into dotfiles, it’s worth calling out how great the community behind them is. When I first forked Paul Irish’s dotfile repo, there was a lot going on in there I didn’t understand. Mathias Bynens and Paul Irish helped me immensely by answering questions about the code and it was their willingness to help that served as one of the reasons I became drawn to both the concept and the community.
Sometimes, I’ll post something to the community that I’d like to automate, but can’t figure it out for the life of me. And, without fail, I’ll get a helpful reply. Case in point: Eric Czarny wrote an app for me to automate my Spectacle settings and Mathias also contributed a code snippet. How cool is that?!
Then there are things like macOS updates. The dotfiles community is often on top of this and provide useful advice on GitHub comments regarding anything that no longer works or other useful information. You can then amend your dotfiles accordingly, such as adding the following code that increases the sound quality for Bluetooth headphones/headsets:
defaults write com.apple.BluetoothAudioAgent "Apple Bitpool Min (editable)" -int 40
Digging into dotfiles
The code example above might look a bit familiar to you. It’s along the same lines as this often-used one to show hidden files:
defaults write com.apple.dock persistent-apps -array-add '{"tile-type"="spacer-tile";}'; killall Dock
These commands can be pasted directly into the Terminal. As you might expect, something like -bool true will change a boolean value from false to true and reset the command for later use.
If you’e like me and have a lot of these commands, then this is where the .macos (previously .osx) dotfile becomes especially useful. Instead of copying and pasting each command individually, we can automate and run all of them in one go.
Let’s walk through some examples
There are so many awesome things we can do in dotfiles. Here are some practical use cases that I rely on for my day-to-day work.
Setting aliases for default commands (.aliases)
Navigating between directories in the Terminal can be cumbersome and it’s easy to get lost in cd madness.
We can replace the standard “change directory” (cd) command with a custom command in the .aliases dotfile. For example, use this alias to ditch the cd prefix altogether when using the command cd .. to move up a directory in favor of .. by itself.
alias ..="cd .."
Sure, it’s only dropping two letters, but how much easier is that to remember?
We can do the same thing to make shortcuts to certain directories:
alias dl="cd ~/Downloads"
Or, create aliases for shorthand command tasks:
alias hs="hexo serve"
Oh, here’s another one! List only directories:
alias lsd="ls -lF ${colorflag} | grep --color=never '^d'"
Make a custom bash prompt for a personal touch to the Terminal (.bash_prompt)
I referenced this a little earlier, but here’s how I turned my bash prompt ($) into a little dude that’s way more fun to look at it. This is done directly in the .bash_prompt dotfile.
PS1="༼ つ ◕_◕ ༽つ"
Create Git shortcuts to speed up commits (.gitconfig)
We can make it a little more efficient to commit all changes at once in the .gitconfig dotfile. Using ca is a lot more concise than !git add -A && git commit -av .
ca = !git add -A && git commit -av
Another handy shortcut: find commits by commit message.
Use Homebrew for package management? Although not strictly a dotfile (it doesn’t have a dot before the file name), Homebrew gives us the brew.sh shell script file. This file automates the installation and management of Apps and Tools:
Hide information you don’t want to share publicly in one file in a private repo and bring it in for you alone. For example, a good idea for this file is anything that’s specific to you, such as your Git credentials. This will prevent people from cloning, running your dotfiles, then committing as you!
# Git credentials
# Not in the repository, to prevent people from accidentally committing under my name
GIT_AUTHOR_NAME="Simon Owen"
GIT_COMMITTER_NAME="$GIT_AUTHOR_NAME"
git config --global user.name "$GIT_AUTHOR_NAME"
GIT_AUTHOR_EMAIL="<ADD-YOUR-EMAIL-HERE>"
GIT_COMMITTER_EMAIL="$GIT_AUTHOR_EMAIL"
git config --global user.email "$GIT_AUTHOR_EMAIL"
Write custom functions for tasks (.functions)
Dotfiles are more than shortcuts and aliases. We can also make custom functions in .functions that do more advanced lifting. For example, create a new directory and change directory to it:
function mkd() {
mkdir -p "$@" && cd "$_";
}
Or, we can open a given location in Finder with a one-letter command (o):
function o() {
if [ $#-eq 0 ]; then
open .;
else
open "$@";
fi;
}
Specify your $PATH and keep private (.path)
$PATH allows the running of executable files. Instead of navigating to each path manually in Terminal, here we can set the file paths so they can run the executable files directly. It might be the case that this file contains sensitive information. As such, this file is often kept in a private repo.
Here’s an example adding ~/utils to the $PATH:
export PATH="$HOME/utils:$PATH"
Force Vim to use a particular theme (.vimrc)
Editor config files are great for ensuring consistent formatting across projects, but we can also tell a Vim editor to use a specific theme in a .vimrc file:
" Use the Solarized Dark theme
set background=dark
colorscheme solarized
let g:solarized_termtrans=1
Bonus: Helpful Terminal recipes for macOS
OK, so here’s a little bit of a bonus for Mac users that isn’t related to dotfiles, but are things we can do in the Terminal to give macOS superpowers to do pretty awesome things that make day-to-day use a little easier and more pleasant.
First off, we can show hidden files by default in the Finder so dotfiles are visible all the time by typing this into the Terminal:
And, in this example, we can automate the size of icons in the Dock:
defaults write com.apple.dock tilesize -int 36
This is only the tip of the iceberg! In my screencast series I go over more than one hundred of them.
Conclusion
Web development is increasingly more complicated as time goes on. We all have ways of making our development workflow a little easier and comfortable based on personal preferences.
You may be a seasoned developer and aware of such things as Node, npm, and Git but still find yourself stuck in a Terminal window with a bunch of errors. Or, you might be starting out and find these, and other tools, complex and tough to grasp.
Either way, hopefully knowing more about dotfiles and what they’re capable of doing gives you a new weapon in your arsenal to make your development environment tailored to you, speed up your workflow and give your machine added superpowers!
As a reminder, my screencast series will give you more tips and tricks, plus a good idea of how to get your development environment set up. This is the first in the series. Going forwards, I’m going to look at expanding on it, so please let me know if there’s anything else you’d like me to cover!
Howdy folks! 🎉 I’m Simon Owen, and over the years, I’ve loved being a part of and learning from the dotfiles community. I spend a lot of time teaching developers and running workshops. In those sessions, demonstrating how I set up my development environment is often one of things that folks appreciated the most.
Dotfiles are a key part of my development environment. Haven’t heard of them? Well, even if you have, it’s a good idea to walk through what they are and the benefits of using them.
If you’re hearing about dotfiles for the first time, it’s totally fine to be confused about what they are and what they do. I recall that it took me a considerable amount of time before I realized a dotfile is simply a file that has a dot in front of the file name!
There are two common examples of dotfiles. First, the ones you might already be familiar with are those often found at the root of many open source projects — for example, .editorconfig contains code editor preferences to help maintain consistent coding styles for a project. You may also have seen .stylelintrc and .eslintrc floating around, which set CSS and JavaScript rules, respectively.
Second (and the ones we’re looking at today), are dotfiles that can live at the root level of a user directory (i.e. /Users/<username> ). One such dotfile is .aliases, which contains custom named commands that can speed up work in the Terminal. Another is .bash_prompt, which is used to change the $ in Terminal to something a little more fun. In my case, I set it so this dude pops up to make me smile when things get tough:
༼ つ ◕_◕ ༽つ
Hopefully, you’re already starting to get a good sense of how useful dotfiles can be. They’re sort of like hidden gems (literally, since they’re hidden from views by default) that unlock superpowers for your machine to help with development. We’re talking about automation, optimizations, and efficient workflows, among other things.
First, I want to give props to the dotfiles community
Before we dig into dotfiles, it’s worth calling out how great the community behind them is. When I first forked Paul Irish’s dotfile repo, there was a lot going on in there I didn’t understand. Mathias Bynens and Paul Irish helped me immensely by answering questions about the code and it was their willingness to help that served as one of the reasons I became drawn to both the concept and the community.
Sometimes, I’ll post something to the community that I’d like to automate, but can’t figure it out for the life of me. And, without fail, I’ll get a helpful reply. Case in point: Eric Czarny wrote an app for me to automate my Spectacle settings and Mathias also contributed a code snippet. How cool is that?!
Then there are things like macOS updates. The dotfiles community is often on top of this and provide useful advice on GitHub comments regarding anything that no longer works or other useful information. You can then amend your dotfiles accordingly, such as adding the following code that increases the sound quality for Bluetooth headphones/headsets:
defaults write com.apple.BluetoothAudioAgent "Apple Bitpool Min (editable)" -int 40
Digging into dotfiles
The code example above might look a bit familiar to you. It’s along the same lines as this often-used one to show hidden files:
defaults write com.apple.dock persistent-apps -array-add '{"tile-type"="spacer-tile";}'; killall Dock
These commands can be pasted directly into the Terminal. As you might expect, something like -bool true will change a boolean value from false to true and reset the command for later use.
If you’e like me and have a lot of these commands, then this is where the .macos (previously .osx) dotfile becomes especially useful. Instead of copying and pasting each command individually, we can automate and run all of them in one go.
Let’s walk through some examples
There are so many awesome things we can do in dotfiles. Here are some practical use cases that I rely on for my day-to-day work.
Setting aliases for default commands (.aliases)
Navigating between directories in the Terminal can be cumbersome and it’s easy to get lost in cd madness.
We can replace the standard “change directory” (cd) command with a custom command in the .aliases dotfile. For example, use this alias to ditch the cd prefix altogether when using the command cd .. to move up a directory in favor of .. by itself.
alias ..="cd .."
Sure, it’s only dropping two letters, but how much easier is that to remember?
We can do the same thing to make shortcuts to certain directories:
alias dl="cd ~/Downloads"
Or, create aliases for shorthand command tasks:
alias hs="hexo serve"
Oh, here’s another one! List only directories:
alias lsd="ls -lF ${colorflag} | grep --color=never '^d'"
Make a custom bash prompt for a personal touch to the Terminal (.bash_prompt)
I referenced this a little earlier, but here’s how I turned my bash prompt ($) into a little dude that’s way more fun to look at it. This is done directly in the .bash_prompt dotfile.
PS1="༼ つ ◕_◕ ༽つ"
Create Git shortcuts to speed up commits (.gitconfig)
We can make it a little more efficient to commit all changes at once in the .gitconfig dotfile. Using ca is a lot more concise than !git add -A && git commit -av .
ca = !git add -A && git commit -av
Another handy shortcut: find commits by commit message.
Use Homebrew for package management? Although not strictly a dotfile (it doesn’t have a dot before the file name), Homebrew gives us the brew.sh shell script file. This file automates the installation and management of Apps and Tools:
Hide information you don’t want to share publicly in one file in a private repo and bring it in for you alone. For example, a good idea for this file is anything that’s specific to you, such as your Git credentials. This will prevent people from cloning, running your dotfiles, then committing as you!
# Git credentials
# Not in the repository, to prevent people from accidentally committing under my name
GIT_AUTHOR_NAME="Simon Owen"
GIT_COMMITTER_NAME="$GIT_AUTHOR_NAME"
git config --global user.name "$GIT_AUTHOR_NAME"
GIT_AUTHOR_EMAIL="<ADD-YOUR-EMAIL-HERE>"
GIT_COMMITTER_EMAIL="$GIT_AUTHOR_EMAIL"
git config --global user.email "$GIT_AUTHOR_EMAIL"
Write custom functions for tasks (.functions)
Dotfiles are more than shortcuts and aliases. We can also make custom functions in .functions that do more advanced lifting. For example, create a new directory and change directory to it:
function mkd() {
mkdir -p "$@" && cd "$_";
}
Or, we can open a given location in Finder with a one-letter command (o):
function o() {
if [ $#-eq 0 ]; then
open .;
else
open "$@";
fi;
}
Specify your $PATH and keep private (.path)
$PATH allows the running of executable files. Instead of navigating to each path manually in Terminal, here we can set the file paths so they can run the executable files directly. It might be the case that this file contains sensitive information. As such, this file is often kept in a private repo.
Here’s an example adding ~/utils to the $PATH:
export PATH="$HOME/utils:$PATH"
Force Vim to use a particular theme (.vimrc)
Editor config files are great for ensuring consistent formatting across projects, but we can also tell a Vim editor to use a specific theme in a .vimrc file:
" Use the Solarized Dark theme
set background=dark
colorscheme solarized
let g:solarized_termtrans=1
Bonus: Helpful Terminal recipes for macOS
OK, so here’s a little bit of a bonus for Mac users that isn’t related to dotfiles, but are things we can do in the Terminal to give macOS superpowers to do pretty awesome things that make day-to-day use a little easier and more pleasant.
First off, we can show hidden files by default in the Finder so dotfiles are visible all the time by typing this into the Terminal:
And, in this example, we can automate the size of icons in the Dock:
defaults write com.apple.dock tilesize -int 36
This is only the tip of the iceberg! In my screencast series I go over more than one hundred of them.
Conclusion
Web development is increasingly more complicated as time goes on. We all have ways of making our development workflow a little easier and comfortable based on personal preferences.
You may be a seasoned developer and aware of such things as Node, npm, and Git but still find yourself stuck in a Terminal window with a bunch of errors. Or, you might be starting out and find these, and other tools, complex and tough to grasp.
Either way, hopefully knowing more about dotfiles and what they’re capable of doing gives you a new weapon in your arsenal to make your development environment tailored to you, speed up your workflow and give your machine added superpowers!
As a reminder, my screencast series will give you more tips and tricks, plus a good idea of how to get your development environment set up. This is the first in the series. Going forwards, I’m going to look at expanding on it, so please let me know if there’s anything else you’d like me to cover!
An irresistible HTML element deep dive from Ire Aderinokun, this time on the <abbr title=""> element for abbreviations. You can kinda just use it (JUI) and it works fine, but if you’re hoping to make a tooltip for them (which works on touchscreens as well), then it’s much more complicated.
The end result is leaving the semantic HTML alone and progressively enhancing with ~50 lines of JavaScript that adds interactive wrapper elements and event handlers.
I feel like this is the perfect sort of thing to be made into a web component that could/should be widely distributed for use. Maybe a <a11y-abbr> component or something. Can you have web components extend other native HTML elements though? If not, I guess it’s kinda falling back to what is essentially a <span>, so maybe that’s not ideal.
Dare I say it, this is also the kind of thing where React can excel. For example, I use Reach Router, and by default, when creating links (<Link>s that turn into <a>s), they get the proper aria-current attribute when it’s the current page. That’s good accessibility you’re getting for free because the library was good enough to get that detail right. As much as libraries like React get pointed at for problematic accessibility, there is a lot of potential for accessibility improvements through abstraction. Sort of like the way Brad Frost has been enforcing accessibility best practices in React components.
An irresistible HTML element deep dive from Ire Aderinokun, this time on the <abbr title=""> element for abbreviations. You can kinda just use it (JUI) and it works fine, but if you’re hoping to make a tooltip for them (which works on touchscreens as well), then it’s much more complicated.
The end result is leaving the semantic HTML alone and progressively enhancing with ~50 lines of JavaScript that adds interactive wrapper elements and event handlers.
I feel like this is the perfect sort of thing to be made into a web component that could/should be widely distributed for use. Maybe a <a11y-abbr> component or something. Can you have web components extend other native HTML elements though? If not, I guess it’s kinda falling back to what is essentially a <span>, so maybe that’s not ideal.
Dare I say it, this is also the kind of thing where React can excel. For example, I use Reach Router, and by default, when creating links (<Link>s that turn into <a>s), they get the proper aria-current attribute when it’s the current page. That’s good accessibility you’re getting for free because the library was good enough to get that detail right. As much as libraries like React get pointed at for problematic accessibility, there is a lot of potential for accessibility improvements through abstraction. Sort of like the way Brad Frost has been enforcing accessibility best practices in React components.
SVG is a great format for icons. Vector formats look crisp and razor sharp, no matter the size or device — and we get tons of design control when using them inline.
SVG also gives us another powerful feature: the ability to manipulate their properties with CSS. As a result, we can make quick and simple interactions where it used to take crafty CSS tricks or swapping out entire image files.
Those interactions include changing color on hover states. It sounds like such a straightforward thing here in 2019, but there are actually a few totally valid ways to go about it — which only demonstrates the awesome powers of SVG more.
First off, let’s begin with a little abbreviated SVG markup:
<svg class="icon">
<path .../>
</svg>
Target the .icon class in CSS and set the SVG fill property on the hover state to swap colors.
.icon:hover {
fill: #DA4567;
}
This is by far the easiest way to apply a colored hover state to an SVG. Three lines of code!
SVGs can also be referenced using an <img> tag or as a background image. This allows the images to be cached and we can avoid bloating your HTML with chunks of SVG code. But the downside is a big one: we no longer have the ability to manipulate those properties using CSS. Whenever I come across non-inline icons, my first port of call is to inline them, but sometimes that’s not an option.
I was recently working on a project where the social icons were a component in a pattern library that everyone was happy with. In this case, the icons were being referenced from an <img> element. I was tasked with applying colored :focus and :hover styles, without adjusting the markup.
So, how do you go about adding a colored hover effect to an icon if it’s not an inline SVG?
CSS Filters
CSS filters allow us to apply a whole bunch of cool, Photoshop-esque effects right in the browser. Filters are applied to the element after the browser renders layout and initial paint, which means they fall back gracefully. They apply to the whole element, including children. Think of a filter as a lens laid over the top of the element it’s applied to.
These are the CSS filters available to us:
brightness(<number-percentage>);
contrast(<number-percentage>);
grayscale(<number-percentage>);
invert(<number-percentage>);
opacity(<number-percentage>);
saturate(<number-percentage>);
sepia(<number-percentage>);
hue-rotate(<angle>);
blur(<length>);
drop-shadow(<length><color>);
All filters take a value which can be changed to adjust the effect. In most cases, this value can be expressed in either a decimal or percent units (e.g. brightness(0.5) or brightness(50%)).
Straight out of the box, there’s no CSS filter that allows us to add our own specific color.
We have hue-rotate(), but that only adjusts an existing color; it doesn’t add a color, which is no good since we’re starting with a monochromatic icon.
The game-changing bit about CSS filters is that we don’t have to use them in isolation. Multiple filters can be applied to an element by space-separating the filter functions like this:
If one of the filter functions doesn’t exist, or has an incorrect value, the whole list is ignored and no filter will be applied to the element.
When applying multiple filter functions to an element, their order is important and will affect the final output. Each filter function will be applied to the result of the previous operation.
So, in order to colorize our icons, we have to find the right combination.
To make use of hue-rotate(), we need to start off with a colored icon. The sepia() filter is the only filter function that allows us to add a color, giving the filtered element a yellow-brown-y tinge, like an old photo.
The output color is dependent on the starting tonal value:
In order to add enough color with sepia(), we first need to use invert() to convert our icon to a medium grey:
.icon:hover {
filter: invert(0.5)
}
We can then add the yellow/brown tone with sepia():
Filters are defined by a <filter> element, which goes inside the <defs> section of an SVG.
SVG filters can be applied to SVG content within the same SVG document. Or, the filter can be referenced and applied to HTML content elsewhere.
To apply an SVG filter to HTML content, we reference it the same way as a CSS filter: by using the url() filter function. The URL points to the ID of the SVG filter.
The SVG filter can be placed inline in the document or the filter function can reference an external SVG. I prefer the latter route as it allows me to keep my SVG filters tidied away in an assets folder.
Right now, this filter is empty and won’t do anything as we haven’t defined a filter primitive. Filter primitives are what create the filter effects. There are a number of filter primitives available to us, including:
[<feBlend>]
[<feColorMatrix>]
[<feComponentTransfer>]
[<feComposite>]
[<feConvolveMatrix>]
[<feDiffuseLighting>]
[<feDisplacementMap>]
[<feDropShadow>]
[<feFlood>]
[<feGaussianBlur>]
[<feImage>]
[<feMerge>]
[<feMorphology>]
[<feOffset>]
[<feSpecularLighting>]
[<feTile>]
[<feTurbulence>]
Just like with CSS filters, we can use them on their own or include multiple filter primitives in the <filter> tag for more interesting effects. If more than one filter primitive is used, then each operation will build on top of the previous one.
For our purposes we’re just going to use feColorMatrix, but if you want to know more about SVG filters, you can check out the specs on MDN or this (in progress, at the time of this writing) article series that Sara Soueidan has kicked off.
feColourMatrix allows us to change color values on a per-channel basis, much like channel mixing in Photoshop.
The color-interpolation-filters attribute specifies our color space. The default color space for filter effects is linearRGB, whereas in CSS, RGB colors are specified in the sRGB color space. It’s important that we set the value to sRGB in order for our colors to match up.
Let’s have a closer look at the color matrix values.
The first four columns represent the red, green and blue channels of color and the alpha (opacity) value. The rows contain the red, green, blue and alpha values in those channels.
The M column is a multiplier — we don’t need to change any of these values for our purposes here. The values for each color channel are represented as floating point numbers in the range 0 to 1.
We could write these values as a CSS RGBA color declaration like this:
The values for each color channel (red, green and blue) are stored as integers in the range 0 to 255. In computers, this is the range that one 8-bit byte can offer.
By dividing these color channel values by 255, the values can be represented as a floating point number which we can use in the feColorMatrix.
And, by doing this, we can create a color filter for any color with an RGB value!
This SVG filter will only impart color to icons with a white fill, so If we have an icon with a black fill, we can use invert() to convert it to white before applying the SVG filter.
If we just have a hex code, the math is a little trickier, although there are plenty of hex-to-RGBA converters out there. To help out, I’ve made a HEX to feColorMatrix converter.