Make ASP.NET bundling specify media=screen for CSS bundle

Viewed 22920

I'm just trying out ASP.NET 4.5 bundling and minification, and ran into an issue.

I've got around 10 css files, of which 2 were originally referenced in the layout using the attribute media="screen".

Since the syntax for adding a css to the bundle does not let you specify that such attribute should be added (makes sense, since the attribute would apply for the whole bundle), I was hoping to see an overload of @Styles.Render that would allow me to specify html attributes, like in other Html helpers, but there is none.

There is an ugly solution, in which since I know the url of the bundle created, i could just craft the tag myself, but I'd lose the caching mechanism that is handled by ASP.NET by allowing it to render the tag itself.

Is there a way to do this, am I missing something? Or is this just an oversight of the design team?

8 Answers

I took Adam Tal's suggestion a little further.

I'm probably over-coding it, but for readability, I created a static class to kind of mimic the Styles.Render format.

public static class StyleExtensions
{
    public enum Format
    {
        Async,
        Preload,
    }

    public static IHtmlString Render(string contentPath, Format format)
    {
        switch (format)
        {
            case Format.Async:
            return contentPath.ToAsyncFormat();
            case Format.Preload:
            return contentPath.ToPreloadFormat();
            default:
            return new HtmlString(string.Empty);
        }
    }

    public static IHtmlString RenderAsync(string contentPath)
    {
        return contentPath.ToAsyncFormat();
    }

    public static IHtmlString RenderPreload(string contentPath)
    {
        return contentPath.ToPreloadFormat();
    }

    public static IHtmlString ToAsyncFormat(this string contentPath)
    {
        return Styles.RenderFormat("<link rel=\"stylesheet\" type=\"text/css\" href=\"{0}\" media=\"print\" onload=\"this.media='all';this.onload=null;\">", contentPath);
    }

    public static IHtmlString ToPreloadFormat(this string contentPath)
    {
        return Styles.RenderFormat("<link rel=\"preload\" href=\"{0}\" as=\"style\" onload=\"this.rel='stylesheet';this.onload=null;\">", contentPath);
    }
}

I would probably erase either the direct constructor or the enum constructor, and you could really put the string extension inside the method too, depending on whatever makes more sense to you, but you'd call it either of these ways accordingly:

@StyleExtensions.Render("~/Content/bundle-bootstrap", StyleExtensions.Format.Preload)
@StyleExtensions.Render("https://fonts.googleapis.com/css2?family=Open+Sans:wght@300;400;700&display=swap", StyleExtensions.Format.Preload)
@StyleExtensions.Render(Url.Content("~/Content/Styles/Primary.min.css"), StyleExtensions.Format.Async)

or

@StyleExtensions.RenderPreload("~/Content/bundle-bootstrap")
@StyleExtensions.RenderPreload("https://fonts.googleapis.com/css2?family=Open+Sans:wght@300;400;700&display=swap")
@StyleExtensions.RenderAsync(Url.Content("~/Content/Styles/Primary.min.css"))
Related