Change the Internet! A Guide to Writing Your First Chrome Extension

Long ago at Atomic Object, we built a custom timekeeping app called Punchit which is functional but not the most beautiful piece of software to grace the internet. After a terrific April Fools’ joke that reskinned the entire app with sparkly frog gifs, I was inspired to try my hand at customizing the look and feel with a Chrome extension.

Note that this approach works best with sites that use human-readable selectors, like id and class.  Sites that use generated CSS classes from frameworks like CSS Modules, Styled Components, and Emotion will be difficult or impossible to adjust because they can change so frequently. Since our tool is internal, I’ll demonstrate on rainymood.com so that you can follow along.

Step 1: Follow the tutorial

Google has a great tutorial to help you set up your very own Chrome Extension. Follow these instructions to get started. At the end, your manifest.json should look like this:

{
    "manifest_version": 3,
    "name": "Hello Extensions",
    "description": "Base Level Extension",
    "version": "1.0",
    "action": {
        "default_popup": "hello.html",
        "default_icon": "hello_extensions.png"
    }
}

Let’s take a minute to customize our extension by finding an icon and updating the popup HTML to be more descriptive. I changed the default_icon to an image of the water droplet emoji and the hello.html with the following content:

In hello.html

<html>
  <body style="background-color: #222">
    <h1 style="font-family: 'Papyrus', sans-serif; color: cornflowerblue">
    My Rainymood Updater
    </h1>
    <script src="popup.js"></script>
  </body>
</html>

And the results look like this!

A screenshot of the updated Chrome Extension popup and button image.

Step 2: Add content.js

Great, now we want to be able to run the extension automatically. To run on any website, we need to update the manifest.json.

{
    "manifest_version": 3,
    "name": "Hello Extensions",
    "description": "Base Level Extension",
    "version": "1.0",
    "action": {
        "default_popup": "hello.html",
        "default_icon": "hello_extensions.png"
    },
    "content_scripts": [
        {
              "js": ["scripts/content.js"],
              "matches": ["https://rainymood.com/*"]
        }
    ]
}

This content_scripts array describes a single rule, which will run scripts/content.js on any site where the URL matches the pattern ”https://rainymood.com/*”. You could throw more wildcards in there if you’d like to be even more generic.

Step 3: Identify CSS to change

Inspect your page to find something in the DOM that fits with what you want to update.  Start by loading your website.  Then you can open the Web Inspector in one of the following ways:

  • Right-click on the page and choose Inspect from the menu.
  • Keyboard shortcuts:
    • Mac: Fn + F12 or Cmd + Option + I
    • Windows: F12 or Ctrl + ShiftI

Screenshot of rainymood.com with the Web Inspector open on the left, before any edits have been made.

Now click the Select button, shown in an orange box below, and hover over the element on the page you’d like to edit.  You should see a blue box appear around it and, in the Inspector panel, the DOM element will be highlighted.  You can click the element on the page to select the DOM element in the Inspector window.

Web Inspector with the Select button highlighted by an orange box.

I’d like to update the color of the text in the “Rainy Mood” header, so here is a video of me selecting that element.

Step 4: Update the DOM with custom CSS

On Rainy Mood, let’s try .center-block , the class of the parent element of this header. Then we can override the white text by using:

// Define the CSS styling you want to inject
const customCss = `
    .center-block {
        color: cornflowerblue !important;
    }
`;

// Create a new style element and set the CSS
const style = document.createElement("style");
style.textContent = customCss;

// Append the style to the document head
document.head.appendChild(style);

By refreshing the extension and then refreshing the page, we see the update here:

Screenshot of rainymood.com with the Web Inspector open on the left, after the first edit has been made.

That wasn’t exactly the effect I was going for. Let’s get more specific and just target the h1 in the .center-block class. We can update the selector in customCss:

const customCss = `
    .center-block h1 {
        color: cornflowerblue !important;
    }
`;

And when we refresh… there, that looks great!

Screenshot of rainymood.com with the Web Inspector open on the left, after all edits have been made.

Great! This served my purpose for now, but what if I want my extension to be more flexible than that? Tune in soon for a future post about how we can use the extension’s popup to get data from the user.

Conversation
  • Creating your first Chrome extension can be a game-changer! This guide simplifies the process, empowering you to customize your browsing experience and enhance productivity. From initial setup to deployment, it’s your gateway to transforming how you interact with the internet. Dive in and start innovating today!

  • “Excited to dive into ‘Change the Internet! A Guide to Writing Your First Chrome Extension.’ Perfect for beginners looking to enhance their browsing experience and develop useful browser tools. Highly recommended!”

  • Join the conversation

    Your email address will not be published. Required fields are marked *