Static Files
Your Flask app needs more than just HTML โ it needs CSS for styling, JavaScript for interactivity, and images for visual appeal. These are called static files because they don't change dynamically like your templates do. Flask serves them automatically from the static folder.
Static Folder Structure
Flask expects static files in a folder called static at the root of your project. Here's a typical layout.
myapp/
app.py
static/
css/
style.css
js/
main.js
images/
logo.png
favicon.ico
templates/
index.html
Flask automatically serves anything in the static folder. You don't need to configure anything โ just put files there and they're available at /static/filename.
Linking Static Files
Instead of hardcoding paths, use url_for() to generate URLs for static files. This is the Flask way and it handles things like cache busting if you set up an extension.
<!-- In your template -->
<link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}">
<script src="{{ url_for('static', filename='js/main.js') }}"></script>
<img src="{{ url_for('static', filename='images/logo.png') }}" alt="Logo">
The url_for('static', filename='...') pattern generates the correct URL regardless of where your app is hosted. If you deploy to a subdirectory later, it still works.
Favicons
Put your favicon as favicon.ico directly in the static folder. Browsers automatically look for it at /favicon.ico. Most templates don't need a special link tag for it โ the browser handles it.
CDN Integration
For popular libraries like Bootstrap or jQuery, you might want to use a CDN instead of hosting the files yourself. This reduces your server load and can be faster for users since CDNs are distributed globally.
<!-- Bootstrap from CDN -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css"
rel="stylesheet">
<!-- Your own styles after -->
<link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}">
The trick is to load CDN styles first, then your custom styles after so you can override Bootstrap's defaults when needed.
Why Flask Serves Static Files Automatically
Flask's built-in static file serving is convenient during development โ no need to set up a separate web server just to serve CSS and images. In production, you'd typically let Nginx or a CDN handle static files for better performance, but for development and small projects, Flask's built-in serving works perfectly fine.