Video Tour of Wagtail 8.0
Published September 19, 2026
This video is from Wagtail CMS 2023 .
Customizing the styling and adding some additional JavaScript functionality to your Wagtail CMS Admin (backend) is often a good idea for user experience and a higher perceived value for clients. In this tutorial I'll show you how to add a custom .css and .js file to your /admin/ area using Wagtail Hooks so you can give your clients a truly customized experience.
Tutorial: https://learnwagtail.com/tutorials/adding-custom-css-and-javascript-to-your-wagtail-admin-area/
Git Commit: https://github.com/CodingForEverybody/learn-wagtail/commit/bd533b96e6f6297e5c5ebf011f6d544f56f6ab88
Learn Wagtail from scratch with the official Wagtail for Beginners Course
https://learnwagtail.com/wagtail-for-beginners/
Used in this video: Wagtail 2.4, Python 3.7, Django 2.1.5
Outro Template made by Grabster - Youtube.com/GrabsterTV
#Wagtail #Django #Python
Wagtail’s admin can be branded and extended without changing its templates by registering custom CSS and JavaScript through a `wagtail_hooks.py` file. The speaker shows how to use the `insert_global_admin_css` and `insert_global_admin_js` hooks, order the assets so they override Wagtail’s defaults, and serve them through Django’s static files. They demonstrate inspecting the admin with browser developer tools, changing selectors such as the sidebar and menu links, and loading a JavaScript file that writes a message to the console. The same approach can point to other paths, including a CDN, rather than Django’s static storage.
Summarised automatically from the transcript.
Automatically transcribed, so expect mistakes in names and technical terms.
Hello and welcome back to another lesson on learning Wagtail, probably the greatest CMS in the world! In this lesson, we are going to learn how to customize our Backend, our administration area with some CSS and some JavaScript. Now it's not going to be a total overhaul or anything like that. I'm simply going to show you how to do it. But to do that, we're going to have to actually get our site up and running. Now I'm going to show you before I get in there. I'm in Users Caleb Tullian Websites MySite. So my site is the name of this website, and I'm going to use Pipenv to get in here. So PipEnv Shell, and you might be using Docker or some other system. That's totally cool. You just need to get into your environment and you need to run manage.
py run server. And this will run on port 8000 by default. And so boot up our browser and let's head on over to localhost 8000. We have our website there, let's go to admin. And we have our administration area. So what we're talking about today is customizing some of the styling in here, maybe adding some JavaScript features, anything like that. We can We can add extra CSS and JavaScript in here without changing the templates. It is a beautiful, beautiful thing. Now I'm also going to share with you my opinion about why you should probably consider doing this. Now, Wagtail out of the box looks pretty decent. It's a fairly minimal CMS, so it's not cluttered with noise all over the place. It has nice contrast, the colors are well thought out.
And your page structure makes sense. However, let's say you have a client or a customer who's paying, I don't know, $20,000 for a website. Or maybe they're paying forty or sixty thousand dollars for a web application and you give them this. And again, there's nothing wrong with this, but You are going to be most likely presenting this to the client who's actually paying you, and they're going to probably want to see a little extra. And with just a little extra effort, you can bring this. All the way home. You can hit you can really hit a home run with them. Even though this is a brownish-gray color, this is a green color. Colors look great in my opinion, and I like it. But maybe it's not quite on brand with your client.
Maybe your client has orange somewhere and they want to see more orange Well you can change that. You can change the sidebar to be orange if you wanted to, or black, or blue, or white. You can change everything. And in a previous lesson, we even got in here. We enabled our style guide, and that brought me to the bottom of the page for some reason. We enabled our style guide. And you can see in here that there's a success message, warning message, error message, all sorts of stuff in here Everything that comes in Wagtail in the admin, you can see in here and you can change those colors entirely. Now as a quick refresher, if you don't know how to do that, you can simply right-click, inspect, and Just move that down a little bit here. So we can see that we've got a list here. We've got a list item with a class of success
So we've got messages, success as the CSS, and the background color is some sort of green. But if we wanted to, we could change that to black and we can see that it takes effect on the left. But if we refresh our page, that's going to go back to the default. Now in my opinion it is a very good idea to just give it a little extra branding for your client And again, that's just my opinion. Feel free to ignore it if you don't want to take my opinion. That's totally okay. That's the nice thing about opinions. They're opinions are totally optional. So in this video I'm going to show you how to add some CSS and some JavaScript. And maybe the JavaScript is for some extra functionality, but this is not going to be a total overhaul, so Don't get super excited that we're going to be changing everything in here because that's going to take a long time. We're just going to change maybe one or two pieces and add a console
log message into our JavaScript so that you can see how this works. So the first thing we need to do after running our server is we need to actually create a new file. And we need to call it Wagtail Hooks. Now this needs to go in some sort of app here. We have a few different apps. Do we have a core app in here? We could go ahead and probably create a core app. So yeah, let's let's do that. Cancel. Manage. py. You know what? I'm gonna move. Can I move that? I can't move that up. I apologize about that. Manage. py start app and we're just gonna call this one core. And if we go back to our editor, we can see we've got core in here.
That's good news. Let's open up our base. py and where we that's not the right one at all. If we open our our website in our settings base. py we will have Where are you? Where are you? Right up here. Installed apps. We already have home, search, flex, streams, site settings, subscribers, blog, menus, contact, and now core. So we can close down this, we can get rid of that, and let's open up our core, and we can see that it comes with models, apps, admin, all that good stuff. We want to create a new file in here though, a new file called Wagtailhooks. py. And let's go back and start up our server. So I'll actually scroll that up so you can see my command was manage. py startappcore. And all I'm going to do now is manage.
py run server. That gets us up and running again on localhost. Refresh. Life looks good And now we get to start the fun part, the actual code. Now, to register some custom CSS or JavaScript in your admin, we have to import a few things here. So that's from Django. contrib Dot static files dot template tags This is a long one by the way dot static files import static from Django. utils. html import format HTML and from Wagtail. core import hooks. And let's separate that a little bit.
So we have three imports here. That first one is a doozy, so feel free to check out the git commit after this video, because that will be in there and you can simply copy and paste that one. So let's register our first hook. So we've got hooks. register, and this one has a specific name. Now there are a lot of Wagtail hooks, like a lot, a lot of them. It's actually really, really fantastic. We're only covering two in this video, and the first one is insert global global yikes admin css, and it takes a parameter called order. And this is really where you want to order your CSS. And because that's sort of hard to describe, let's uh let's view the page source.
So we have core. css in here, we've got uh jQuery tagit. css, and we've got jQuery UI in here. That ordering is like where does it go? We also have style guide in here, draft. css, draft tail. css. Where does it go? Where do we want to order it? Do we want to order it at the very beginning and let Wagtail overwrite our stuff? Or do we want to put it at the very end and overwrite everything? I'm in favor of putting it at the very end and just overriding what we need. And so I'm going to throw an order of 100 in here Next we need to actually define some sort of function in here. So let's call this, I don't know, global admin css. It's a simple function, it takes absolutely nothing for its parameters little
doc string in here I don't know add static css slash custom dot css To the admin. Something like that. And here comes the tricky part. Actually, it's not tricky at all. It just sort of looks like a lot. It looks like a mouthful, but. I'll break it down for you. So format HTML and we want to throw some formatting in here Uh let's add a link. Let's add the rel is going to be a style sheet. And an href is going to be Something we're not entirely sure yet. Close that tag and we have an HTML tag. And I'm gonna make this just a tad bit smaller, because
that largeness is gonna get a little tricky. Now from that, we want to add static css slash custom dot css. Save. We've got a problem here. It's hooks, not hook. Everything looks okay. Check our Terminal, no module named Dango. It's because I forgot the J. If you're screaming at the screen saying, Caleb, you forgot the J, good catch. Okay, things are looking alright. And now if I refresh here, you can see that we have a brand new style sheet. I'll make that just a bit bigger. And it just says custom or static CSS
custom. css. Now that file does not exist. And we can actually see that when we go here, it's going to throw us an error. Yeah. Page not found 404. That is actually acceptable. That is sort of what we're looking for. That means it's actually looking for the file. And honestly, that's good news. That's good news that it doesn't exist because all we have to do is make that file exist. So let's go into our static Where are we? MySite. Let's go into NutSettings, static, CSS. We already have mySite. css and let's add a new file called, I don't know, custom. css, because that's what we called it in our hook. That matches This name. Now the reason I'm breaking this out into a separate CSS
file and I'm not just writing it inside of mysite. css is Because you don't necessarily want to write CSS that's going to be loaded on every single page if nobody's ever going to see it. I come from a slightly older generation of uh internet web developers, and The idea was to only give users what they're asking for. And when someone comes into the admin area, do do do do do this area, then they get some extra styling. Otherwise, on the rest of the site, don't bother with it. Basically what I'm saying is mySite. css could be for your actual website, and custom. css could be for your admin area. And you can rename those appropriately if you like. But now we need to add some custom CSS.
So I'm just going to add something ultra ugly. Everything is going to get a border of one pixel solid red. And let's go refresh. And you can see that I just wrecked this. I destroyed it, it looks terrible. But it works. And that's all it needs to do, is it just needs to work. So I'm going to get rid of that, refresh, and let's say we want to change just this sidebar color. Which disappears when I use this. So let's change do do do do do doc to bottom. There we go. And I want this to be lower. And probably smaller so that I can actually read it. Alright. Right click and inspect, and we can see we have this class called inner
And in our inspect element, if you just click the actual element that you want to change the styling for, so we've got nav wrapper, that's this whole thing in here. We've got inner. Where does inner lead? So enter the whole thing. We've got an explore wrapper. We can do all sorts of things in here. Anyways, I'm not going to get too caught up in that. I just want to change something like inner. So when you click here on the right side, you can see we've got nav wrapper. inter. And this is our selector here. That's our CSS selector. And what would happen if we looked for a background color? Background color. Oh, there it is. So it's nav wrapper. inter. That's our background color. And if we change that to red, we can see it changes to red. So all I'm going to do is grab this particular selector.
In fact, I only want the one that's highlighted, not the gray one, but the one that's almost a black font. And I'm going to grab that. And let's change the background color. Background color and I don't know, let's make it orange It's gonna look terrible, but it's gonna work. And there we go. So now we can change that to orange, but you can see there's some other Color accessibility issues obviously you can't see any of that text in there so maybe orange was a terrible choice. Let's go with black Looks a little bit darker. The Wagtail bird is sort of hidden. Doesn't look terrible. And if we want to change something in here like let's change this link color.
So we've got a menu item. And we've got the link. So let's take a look at this link. And that color. We want to look for the color in here. Nice. There's a transition. Border left. Yep. Yep. Yep. Color CCCCC. Let's change that to. F00 changes it to red. Beautiful. So I know that's the right one. I'm gonna grab that selector, go back into my custom. css. Paste that in there and change the color to white. So it's black on white. And by white, if you're screaming at the screen again saying, Caleb, that's not white. Yeah, it's one of those days for me. Alright. Close that and now we have a nice black menu on the left
and we have white links. We can go ahead, we can do the same thing with that. We can go through our entire style guide. We can change all the colors in here, we can change all the different styles, we can do all that stuff. So now we are customizing our CSS. Now just as a heads up, I'm not going to leave it this way. When I commit this, I'm going to leave this actually I'm going to comment this out right now. Uh so that When you clone this repository down, it's actually going to look normal and you're not thinking, oh my goodness, why does it look so different on every other video except this one? But that is really all there is to adding CSS. And it really comes down to this Wagtailhooks file, which it does have to be called Wagtail underscore hooks. py. And all we did was add three imports and a little function.
Now let's add some JavaScript in here. Let's. Let's add some fun stuff. And by fun, I mean it could be fun, but I'm going to make it boring. Uh make some room down here. So hooks, register, and this one is insert global adminjs. And the order again, let's put that at the very bottom Def Global Admin JS takes nothing Some doc string in here, describe what you're putting in there. And again, it really just comes down to this formatting. Format. html, and I'm going to put a script in here this time, script. With a source
end script and static jscustum dot js and maybe First of all, touch that up, but also maybe let's put this on different lines. Just because in this video it's going to be easier to read it on separate lines. Alrighty, so that's that. Let's head on over to our source. And just to show you how I got to the source, right-click view page source. And that's pretty much global right across any browser you use, but I'm using Firefox. And let's head on down to the very bottom. So I've got Django debug toolbar, that's taken up a lot of stuff in here. Custom. js
And we can see we're using jQuery for a lot of stuff already. That's pretty nice, so we can just start using jQuery as is. But we have our static. jscustom. js. And again, we click it, it's going to say that this page is not found. Just like that. And so now we just have to make that file exist. And we are going to do something a little quicker, because I don't want this video to go on for too long. You have a life to live still. Let's call this custom. js and I just put that in the in the static slash js folder and all I'm going to do is consolog hello world. This is a message from learnwagtail Wagtail dot com. And now when I refresh this page, you're gonna see that absolutely nothing happens, but let's inspect our element and go to our console log.
And let's let's log everything. Let's get rid of XHR. Uh let's see errors, warnings, logs. There it is. Info and debug. And we can see all sorts of stuff in here. And we can also see hello world. This is a message from learnwagtail. com. That is our custom message and it's coming from custom. js. We can even click it and it will show us the actual code in here. So your dev tools, your inspector is super super important when working with a lot of this stuff. Uh but getting up and running with it is nice and easy. And just as a little refresher, we created a file called Wagtail underscore hooks. py. And we imported probably the longest import known to humanity. Uh we imported format HTML and Wagtail Hooks, which basically just allow.
. the code to run and then once it's done running adds a little extra something in there. A little something c a little custom stuff. A little extra custom CSS or JavaScript in this case, but it could be basically anything. We learned how to add global admin CSS and global admin JavaScript. We learned about the ordering, formatting, and static. Uh one thing I didn't go over that I'm going to go over right now is the static thing. So basically format HTML is going to take one parameter and in this part here where we have these funky little curly braces. All that is saying is whatever that next parameter is, throw it in here. We use a static function to basically automatically append static in there
Which is pretty standard for most Django websites, but your website might not be static. It might be media, it might be uploads, it might be custom, it could be anything really. It might not even have static. It might just Be loaded from some content delivery network. And if that's the case, get rid of static. This could be Cd what oops cdn. cloudflare. com slash thing slash lib. js. Obviously with your protocol in front of it. HTTPS. Something like that. So you can do that. Now with all of that said, we are good to go. I'm going to leave this in here. You can always access this code in the git commit, which I will leave down below.
Hey there, my name is Caleb Tallin. I am a Wagtail Core team member, and I just wanted to say thank you for watching this video about learning Wagtail CMS. If you enjoyed this video, there are plenty more where this came from. all available on learnwagtail. com and if you would like to dive into any particular subject you can always go to docs. wagtail. io the documentation is quite fantastic and in true Python fashion it is very well written. And hey if you like this video don't forget you can always share, subscribe, or leave a comment down below. I love hearing from the community. And I look forward to seeing you in the next video
Create a `wagtail_hooks.py` file in an installed app, register the `insert_global_admin_css` hook, and return a stylesheet link using Django’s `static()` helper. Then create the referenced CSS file in your static CSS directory and add the desired admin styles.
Discussed at 6:13Pass a high `order` value, such as `100`, to `insert_global_admin_css` so the stylesheet is loaded after Wagtail’s built-in CSS. This lets your selectors override the default rules where needed.
Discussed at 6:58A separate file keeps admin-only styling from being loaded on every page of the public website. The site stylesheet can serve the front end, while a file such as `custom.css` is loaded only for the admin area.
Discussed at 10:01Register the `insert_global_admin_js` hook in `wagtail_hooks.py`, return a script tag pointing to a static JavaScript file, and create that file in the static JS directory. The example adds a console message, which can be verified in the browser’s developer console.
Discussed at 14:43Note: We understand that names change, people change, and bodies change. We respect each individual's journey and privacy. If you have any concerns about a video or need us to remove content, please don't hesitate to contact us. We will handle your request with care and promptly address any issues.
Published September 19, 2026
Published July 9, 2026
Published May 20, 2026
Published April 16, 2026
Published April 1, 2026
Published March 10, 2026