Manually Minifying Inline CSS in PHP
Smaller is Better
Most everyone in today's development world knows that you need to "minify" your static content (CSS and JS) to reduce the size of these assets. This can make client side downloads much faster, especially for users on slower Internet (which is a lot more people than you might assume).
So why is it that most websites don't minify HTML? First, how can you really minify the page content itself? It isn't like you can shorten the name of tags or eliminate text. All you can really do is strip out whitespace. It just isn't worth the small gains considering that HTML will be served gzipped, anyway.
Actually, this is not entirely true. I might argue that lazy loading of images is a sort of HTML minification; it requires changing the structure of the HTML so that the client downloads far, far less data as the DOM is loading. Isn't that basically the same goal?
Why Would you Ever Minify Inline CSS?
Using inline CSS is generally bad practice for a good reason. I almost don't even feel that I need to explain why. Obviously organizing your code into files is logical and good practice. It's also more efficient in most contexts. Yes, you do incur an extra web request to serve a CSS file...but as people navigate your site, that CSS can be cached on client machines.
If you include inline CSS, you don't get that benefit. Each page has more weight and the same CSS will be downloaded fresh every time. That's not the best use of bandwidth, but it is a tradeoff. In some use cases, it may even be a valid tradeoff.
Best practice is so called because it's the "best" practice, not the only practice. There's infinite possible software that can be written and no one can understand every use case or context. It isn't so crazy to imagine a use case where inlining CSS is more efficient than serving it as a separate file.
Most packages (including Laravel Mix) work by using javascript build pipelines and presume that you will minify CSS files. Of course this is a valid assumption for most every use case, but what if you want to do this programmatically?
Minifying CSS in PHP
Fortunately, we're in the PHP universe where adding packages via composer is very easy. Let's start by installing an existing, robust PHP-based minifier:
composer require matthiasmullie/minify
You can read more about this package here. I will go into a slightly deeper dive if you'd prefer to implement your own minifier, as implementing a CSS-only minifier is not that hard.
We can still organize our inline CSS into a file, then inject it into a view to pass to the layout. This way, we can avoid an extra web request to fetch CSS (if that's what your goal really is) while still gaining some benefit of better organization. Here's an example:
$sourcePath = public_path('css/article-layout.css'); $minifier = new Minify\CSS($sourcePath); return $minifier->minify();
This returns minified CSS from a file.
Of course, it wouldn't make much sense if we were doing this from a view directly presented to the end user, but in this case, the application is a content builder. The nature of this application requires "baking" pages into a cache-able format that's hosted without a server, so inlining the CSS does make sense.
Is it the best approach? Perhaps not, I could use the conventional build pipeline, but that would require extra logic to upload and invalidate files after each change and introduces a soft dependency in what is supposed to be a self-contained static file. For the twelve people that will ever read this blog...the added efficiency of those few bytes doesn't seem like a good tradeoff.
Wrapping This Into a Layout for Laravel
In my case, I handle all static page building in a dedicated service class. This makes it easy to pass the minified CSS into the article view. There, I can easily pass it to the layout; Laravel 10 makes this very easy:
<x-slot:css>{{ $inline_css }}</x-slot:css>
Now the layout can simply output any inline CSS and remain somewhat flexible in case other content types need specific CSS (or if I want to combine multiple files into one).
To be clear, 9 out of 10 times it's far more logical to do this the "normal" way. Use Mix or Vite! It's unusual to need to inline CSS, but unusual things happen all the time!
Do we Really Need a Package...?
I feel like this article is incomplete because the bulk of the logic here is being handled by a composer package. Let's implement a basic version of a CSS minifier ourselves.
We know the basic idea, that we minify files to reduce their file size. Smaller file size means faster downloads for clients, and that makes everyone happier. For CSS, we need to remove any comments, whitespace, and new lines. That's not that hard with some regex.
Using the same file as above, we can achieve a similar minified output with this:
// obtain the file contents (public_path is a laravel method) $css = file_get_contents(public_path('css/article-layout.css')); // remove comments, then whitespace/newlines $css = preg_replace('!/\*[^*]*\*+([^/][^*]*\*+)*/!', '', $css); $css = preg_replace('/\s+/', ' ', $css); $css = str_replace(array("\r\n", "\r", "\n", "\t"), '', $css); return trim($css);
That said, if you (for some reason) also need minified JS, you might want to stick with a package like the above that can do both.
That's All!
Again, you probably don't want to inline CSS...but with an infinity of use cases in the universe, it isn't my place to dictate what is or isn't a good idea.
Hopefully your found this useful. If you didn't, no one forced you to read it, so I guess that's on you...?