Designing CSS for Canvas Project

Designing Custom Style Sheets for Canvas

With custom CSS, you can jazz up the look and improve the LX of your Canvas courses.

You may be wondering why you should add CSS to your Canvas instance. To style pages, many learning designers and faculty either rely on Canvas’s rich content editor, or if they know a bit of HTML, they use inline styling to format content in pages and description areas of their Canvas course. However, both of these methods can be very time-consuming, making revisions if you decide to change your content’s formatting is a tremendous amount of work, and at the end of the day, you simply can’t do as much with inline styling as you can with CSS.

While writing CSS for two institutions (University of Notre Dame and Miami University Ohio), I ran into several challenges that I outline here for you. In addition, I share some recommendations for writing CSS when multiple people (some new to creating digital content) will be using your code. Hopefully, knowing all of this in advance will save you time!

NOTE: Canvas allows you to upload a CSS file in the Admin panel under the “Themes” options. If you don’t have administrator privileges to your institution’s Canvas instance, make friends with someone who has access (or can give you access) to the Themes settings in its Admin panel.


#1: CSS runs at the subaccount level.

It’s good to know that a CSS file has to be uploaded to a subaccount in Canvas, which means you can’t run it in just one course or a single page in a course. Also, you don’t have access to an individual page’s header or footer, so you can’t link to a CSS file you’ve uploaded somewhere outside of Canvas. You can only use a file you’ve uploaded to it.

#2: Your CSS will be loaded everywhere.

Canvas is going to display a lot of warnings about adding custom CSS, and for good reason: Your styling affects not only content you’re adding to a course but also your Canvas instance’s interface elements. You’ll want to be very cautious about the names you use for classes and ids since you may accidentally repeat names already being used in Canvas’s own CSS, which means your CSS will override Canvas’s base CSS. Therefore, changes you make to elements like headings and lists have the potential to really skew the styling of dashboard items, menus, etc. throughout the entire system.

#3: You’ll need to create two different CSS files.

You’ll have to create a CSS file for the web-based version of Canvas and a separate CSS file for the Canvas mobile app, then upload both in the Themes settings. That said, I still opt to add media queries for relatively small widths in my CSS for the web because someone may reduce the size of their browser window to very tiny dimensions.

#4: Not all code will work.

Canvas will straight-out block certain things, notably HTML code for forms and any fonts except for web-safe ones. Sadly, this means you can’t use your own custom fonts or Google fonts, nor can you load icon fonts, like Google Material icons or Font Awesome.

#5: Device breakpoints are *not* normal.

If you’re writing your own CSS for Canvas and you’re working in an editor that lets you preview your work at specific device breakpoints or you’re adding in typical ones with media queries, it just ain’t gonna work right. Your page’s width in Canvas is going to vary depending on whether someone’s viewing it in Pages or Modules (i.e., it’ll be narrower in Modules because the page has a right sidebar). Also, Canvas pages resize responsively as screens get smaller to a certain point—then the left navigation menu disappears and BAM! Your page is suddenly wider.

In addition to these two considerations, Canvas has no maximum width set for pages, so you may want to set them in your CSS so that users with ultra-wide monitors aren’t trying to read lines of text that are hundreds of characters long or looking at pixelated images.

#6: Styling from your CSS isn’t visible at some times.

This confuses people who are new to working with HTML and CSS! When you open a page, assignment, etc. in Canvas to edit it, it can no longer “read” your CSS file, so the page loses any styling your CSS is adding. Also, styling from your CSS doesn’t display in Canvas Commons because your content is no longer in the same subaccount where your CSS file is loaded. I try to warn faculty about these two things up front so that they don’t assume that they somehow accidentally “broke” something.


In addition to the challenges listed in the previous section, I ran into another one while piloting my CSS: It was being used by lots of other people, both faculty and instructional design staff. If I didn’t write my CSS so that adding HTML code was simple and updates were easy to make through the rich content editor, I was leaving myself open to being bombarded with requests for help.

Unless you’re in the blessed situation of not having to share your CSS with anyone else or if you’re a rare breed—someone who enjoys spending a lot of time picking through someone else’s HTML code to fix issues—you’ll want to take all of these workarounds into consideration.

To style basic elements, wrap an entire page in a special div class.

One practice I highly recommend is creating a special div class for a container that you’ll use to wrap all of the content on a page or in a description area. In your CSS, you’ll add that class to all of the basic elements you’ll be using (like headings, lists, and hyperlinks) and specify their styling. Then, rather than having to add classes to each and every element on the page, you can simply add the HTML code for the div container at the top of your page, and your styling will automagically be applied to all of its elements.

In addition to requiring less manual HTML code editing for anyone creating pages, this container will prevent your CSS from affecting Canvas’s interface elements (Challenge #2). Also, you can also use this class to constrain the overall width of a page (part of Challenge #5).

If you want to vary styling between courses within the same subaccount, you’ll find that this workaround has another benefit: Using a special div container to apply styling to an entire page will allow you to apply completely different style templates within the same subaccount (Challenge #1). The only exception here is title of a page—since it’s outside of the div container you wrap around a page’s content, your page titles will need to be the same across an entire subaccount.

Save icon images in a central location.

Because Canvas won’t allow you to load icon fonts, my icons are images. For example, here I’ve created icons for assignment categories that were designed in collaboration with Miami University’s Special Education faculty. These icons are simply images that are added to the page and styled by a class in my CSS.

Icons used in a Special Education course to indicate different types of assignments: activate, integrate, engage, apply.

I found it best to store icon images in a central location and link to them rather than loading them in a Canvas course. (The backend of a website, like a WordPress site’s media library, works well.) This prevents a common issue: Faculty and staff will sometimes try to copy a page’s content and paste it into another course, but while text can be copied and pasted, images cannot! Also, using a central location to store images means you can share them with select members of your team, so you’ll have backup if someone needs to access them while you’re away.

On top of these two benefits, centrally stored icons make it easier to create template pages that can easily be copied and pasted as HTML code—no need to copy anything from one course to another or rely on Canvas Commons (part of Challenge #6). While you can allow people to copy your code from a Canvas page, after some trial and error I found it easier to use CodePen to share my HTML template pages. It’s easy to embed pens, so I added them to an HTML repository course I have set up in Canvas for my fellow instructional designers and faculty members to use. Overall, it requires fewer clicks for them to copy code from the CodePen embed, and the fewer people who have instructor-level access to a course, the less likely it is that something in the course will accidentally be changed.

CSS Flexbox is the best option for creating columns.

When I first wrote CSS for Canvas, I made some fairly complicated layouts for images and text, but a lot of folks really struggle with sizing images for responsive design, or they want to include too much/too little text for a layout to work right. I’ve found that it’s better to keep things as simple as possible—you just can’t count on people showing up with specific amounts or sizes of text and images.

This means that CSS Flexbox is your best option for laying out content in rows and columns. Plus, it’s easier for HTML newbies to code, and regardless, Canvas pages don’t provide enough space for more complex layouts.


I’ve set up a few examples from my own Canvas styling in a CodePen collection so that you can quickly and easily add it to your own instance by copying and pasting my CSS and HTML code.

Screenshot of a call-to-action header for a Canvas course

Call-to-Action Hero Header

I developed this header with a hero image to add call-to-action content at the top of a Canvas course page. It includes a button that directs students to a specific spot in your course or an external website.

Get the code

Image-Based Menu

You can use this code to create an image gallery with text overlay or add links to the images to create a menu. I frequently use it to create a menu of a course’s modules on its homepage.

Get the code

Screenshot of a Canvas page header with a styled title, new subtitle, and dark introduction block

This code styles a page’s title and allows you to add a subtitle below it. It also creates a block where you can add a short text introduction to your page.

Get the code


With accordions, you can include a lot of content on a page without taking up very much real estate. They work well for FAQ lists, glossaries, or content that you want to initially hide, like answers to practice problems.

Get the code