What the error looks like
The page loads but has no styling, and assets 404. In the browser console you see:
GET https://example.com/css/app.css 404 (Not Found)
Refused to apply style from '.../app.css' because its MIME type ('text/plain') is not a supported stylesheet MIME type
The nginx access log confirms it:
1.2.3.4 - - [16/Jul/2026:14:02:11] "GET /css/app.css HTTP/1.1" 404 153
Why it happens
Several different problems all show up as "my CSS will not load":
-
Wrong
rootoralias. Nginx looks in the wrong folder, so the file is not there. See root and index and alias. -
Missing
include mime.types. Without it, CSS is sent astext/plainand the browser refuses to apply it. See mime types. -
Missing or wrong
try_files. The request never resolves to the real file. - Permissions. The nginx user cannot read the asset.
-
A greedy front controller. In a Laravel or SPA config,
try_files $uri $uri/ /index.phpcan send asset requests to PHP instead of serving the file.
How to fix it
- Make sure MIME types are included. This is the fix for the
text/plainwarning. It belongs in thehttpblock, usually already in the mainnginx.conf:
http {
include mime.types;
default_type application/octet-stream;
}
- Confirm
rootpoints at the directory that actually holds the assets, and that the file exists there:
ls -l /var/www/html/public/css/app.css
- For a Laravel or SPA site, put
$urifirst intry_filesso real files are served before falling back to the front controller:
location / {
try_files $uri $uri/ /index.php?$query_string;
}
Because $uri comes first, /css/app.css is served as a file and never reaches PHP.
- Fix permissions if needed, then reload:
sudo chown -R www-data:www-data /var/www/html
sudo nginx -t && sudo systemctl reload nginx
Common mistake
Trailing slash confusion with alias. If your location /assets/ uses alias, the alias path must end in a slash too. A missing slash makes nginx build the wrong file path and every asset 404s.
Another one that hides in plain sight: a regex location. A block like location ~* \.(css|js|png)$ { ... } wins over your normal location /, because regex locations are matched before prefix ones. If that block sets a different root, or forgets to set one, your assets 404 while the rest of the site is fine. When only certain file types break, look for a regex location handling exactly those extensions.
FAQ
Why is my CSS served as text/plain?
Nginx does not know the file is CSS. Add include mime.types; in the http block. That maps .css to text/css so the browser accepts it.
Assets 404 only after I added a PHP app. Why?
Your try_files probably sends everything to index.php. Keep $uri as the first fallback so existing files are served directly and only missing paths reach PHP.
The file exists but still 404s. What now?
Check the path nginx is actually building. Turn on the error log, request the asset, and read the open() "..." failed line. It shows the exact path nginx tried, which usually reveals a wrong root or alias.