It’s not elegant but it works.
Add these lines to functions.php:
ob_start();
add_action('shutdown', function() {
$final="";
$levels = ob_get_level();
for ($i = 0; $i < $levels; $i++) {
$final .= ob_get_clean();
}
// append styles just before </head>
$final = str_replace( "</head>", '<link rel="stylesheet" src="https://wordpress.stackexchange.com/questions/271293/mycss.css"></head>', $final );
echo $final;
}, 0);
Alternatively you can move all the inline styles at the beginning of the head, better if just after the title tag:
ob_start();
add_action('shutdown', function() {
$final="";
$levels = ob_get_level();
for ($i = 0; $i < $levels; $i++) {
$final .= ob_get_clean();
}
/* Adjust the final output */
// load HTML DOM
$dom= new DOMDocument();
$dom->preserveWhiteSpace = false;
$dom->formatOutput = true;
$dom->loadHTML( '<?xml encoding="utf-8" ?>' . $final );
// collect styles and remove them from DOM
$inline_styles = "";
$styles = $dom->getElementsByTagName("style");
foreach( $styles as $style )
{
$inline_styles .= $dom->saveHTML( $style );
$style->parentNode->removeChild( $style );
}
$final = $dom->saveHTML();
// strip utf-8 workaround
$final = str_replace( '<?xml encoding="utf-8" ?>', "", $final );
// append styles after <title>
$final = str_replace( "</title>", "</title>\n" . $inline_styles, $final );
echo $final;
}, 0);