It’s also worth your time to learn the most powerful CSS selectors, because you use those selectors all the time to speed up your work when you’re writing rules.
Programming errors, too, are a fact of web coding life, so understanding the most useful JavaScript debugging strategies can help you fix your code faster and get back to more creative pursuits.
Your ready-to-roll HTML template
All web pages use more or less the same basic HTML structure. This means you can get any new web project off on the right foot by first laying down a solid foundation that includes valid HTML and semantic page tags.
Rather than create this foundation from scratch each time, you can save yourself some time along with wear and tear on your typing fingers by creating a template file that you can copy for each new project.
To get you started, here are the HTML tags to add to your template:
<!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Barebones HTML Template</title> <style> /* * Put your internal styles here or replace with * <link href="filename.css" rel="stylesheet"> */ </style> </head> <body> <header> <h1>Site Title</h1> </header> <nav> Navigation links </nav> <main> <article> <h2>Article Title</h2> </article> <aside> <h3>Aside Title</h3> </aside> </main> <footer> Footer stuff </footer> <script> /* * Your internal JavaScript goes here. * Alternatively, replace with * <script src="filename.js"></script> */ </script> </body> </html>
For the <link> and <script> tags, be sure to adjust the filenames as needed, and be sure to add the path to each file if you’ve stored them in subdirectories.
15 must-know CSS selectors
CSS saves you oodles of time by making it easy to style page elements. CSS becomes even more powerful when you use selectors to specify which elements you want to work with.
Here are the selectors you need to tape to your cat’s forehead so that they’re always handy:
The class selector
If you’ve used the class attribute to assign a class name to one or more page elements, you can target those elements by using a class selector:
HTML:
<element class="class-name">
CSS:
.class-name { property1: value1; property2: value2; etc. }
The id selector
If you’ve used the id attribute to assign an ID to a page element, you can target that element by using an id selector:
HTML:
<element id="id-name">
CSS:
#id-name { property1: value1; property2: value2; etc. }
The type selector
To target every element that uses a particular element name (such as header or div), use the type selector:
element { property1: value1; property2: value2; etc. }
The attribute equals selector
To target every instance of an element that uses an attribute with a specified value, use the attribute equals selector:
element[attr="value"] { property1: value1; property2: value2; etc. }
The descendant combinator
To target every element that’s contained within (that is, is a descendant of) a specified ancestor element, use the descendant combinator (a space):
ancestor descendant { property1: value1; property2: value2; etc. }
The child combinator
To target every element that resides one level below (that is, is a child of) a specified parent element, use the child combinator (>):
parent > child { property1: value1; property2: value2; etc. }
The subsequent-sibling combinator
To target every sibling element that follows a reference element, use the subsequent-sibling combinator (~):
reference ~ target { property1: value1; property2: value2; etc. }
The next-sibling combinator
To target the sibling element that comes immediately after a reference element, use the next-sibling combinator (+):
reference + target { property1: value1; property2: value2; etc. }
The first-child or last-child pseudo-classes
To target any child element that’s the first or last of a parent element’s children, use the first-child or last-child pseudo-class:
element:first-child { element:last-child { property1: value1; property2: value2; etc. }
The nth-child or nth-last-child pseudo-class
To target any child element that’s the nth or nth-last of a parent element’s children, use the nth-child or nth-last-child pseudo-class:
element:nth-child(n) { element:nth-last-child(n) { property1: value1; property2: value2; etc. }
The :is() pseudo-class
To target elements that match any of the selectors in a specified selector list and where the overall specificity of the selector is the highest weight of the items in the selector list, use the :is() pseudo-class:
element:is(selector-list) { property1: value1; property2: value2; etc. }
The :where() pseudo-class
To target elements that match any of the selectors in a specified selector list and where the overall specificity of the selector is 0, use the :where() pseudo-class:
element:where(selector-list) { property1: value1; property2: value2; etc. }
The :not() pseudo-class
To target elements that don’t match any of the selectors in a specified selector list, use the :not() pseudo-class:
element:not(selector-list) { property1: value1; property2: value2; etc. }
The :has() pseudo-class
To target an ancestor, parent, or previous sibling that has a descendant, child, or sibling (respectively) in a specified selector list, use the :has() pseudo-class:
element:has(selector-list) { property1: value1; property2: value2; etc. }
Top 10 JavaScript debugging strategies
Given any nontrivial JavaScript code, it’s a rare (probably nonexistent!) script that runs perfectly the first (or even the tenth!) time.
Script bugs happen to even the most experienced developers, so having errors in your code does not mean you’re a failure as a coder! All it means is that you’re a coder.
But when bugs get into your code, you’ll want to exterminate them as quickly as you can. Here are ten debugging strategies that can help:
- Get thee to your dev tools: All web page debugging begins with a visit to your web browser development tools. In every browser, the quickest way to open the dev tools is to right-click a page element and then click Inspect. You can also press Ctrl+Shift+I (Windows) or Option@@cmd+I (macOS).
- The console is your best debugging friend: In your code, you can see the current value of a variable or object property by outputting that value to the dev tools Console tab:
console.log(output);
- output: The expression you want to print in the Console. The output expression can be a text string, a variable, an object property, a function result, or any combination of these.
- Give your code a break(point): Pausing your code enables you to see what’s going on and to run some commands in the console. You have two ways to pause your code mid-execution:
- Set a breakpoint: In the dev tools, open the file that contains the JavaScript code, locate the statement where you want to pause, and then click the line number to the left of that statement.
- Add a debugger statement: In your JavaScript code, on the line just before the statement where you want to pause, add a debugger statement.
- Step through your code: Once you have some JavaScript code in break mode, use the dev tools execution controls to step through the code. You can step one statement at a time, step over functions, or step into functions.
- Monitor variable and object property values: Either use console.log() statements to output values to the console or, when your code is in break mode, hover the mouse pointer over the variable or object to see its current value in a tooltip. You can also create watch expressions to monitor values.
- Indent your code. JavaScript code is immeasurably more readable when you indent the code within each statement block. Readable code is that much easier to trace and decipher, so your debugging efforts have one less hurdle to negotiate. Indenting each statement by two or four spaces is typical.
- Break down complex tasks. Don’t try to solve all your problems at once. If you have a large script or function that isn’t working right, test it in small chunks to try to narrow down the problem.
- Break up long statements. One of the most complicated aspects of script debugging is making sense out of long statements (especially expressions). The Console window can help (you can use it to print parts of the statement), but it’s usually best to keep your statements as short as possible. Once you get things working properly, you can often recombine statements for more efficient code.
- Comment out problem statements. If a particular statement is giving you problems, you can temporarily deactivate it by placing two slashes (//) at the beginning of the line. This tells JavaScript to treat the line as a comment. If you have a number of statements you want to skip, place/* at the beginning of the first statement and */ at the end of the last statement.
- Use comments to document your scripts. Speaking of comments, it’s a programming truism that you can never add enough explanatory comments to your code. The more comments you add, the easier your scripts will be to debug.