Search code examples
c#asp.net-corerazorasp.net-core-6.0asp.net-core-tag-helpers

ASP.NET Core asp-fallback tag helper with pseudo selectors (and bootstrap-icons)


I'm using ASP.NET Core 6, with the asp-fallback feature of the <link> tag helper (I know how to use it, and it works well for me).

I'm also using the Bootstrap Icons library. I can't get it to work with fallbacks because it uses pseudo selectors only (example).

Is there a way to use the fallback mechanism with pseudo selectors? If not, is there some workaround?


Solution

  • The LinkTagHelper fallback mechanism does not support pseudo selectors. There is a tracking issue on the repo, so maybe it'll be fixed in v7.

    Until then I'm using a WORKAROUND. I extended the framework's fallback code to also consider pseudo selectors.

    Add this to the DOM:

    @{
      var testClass          = "bi";
      var testPseudoSelector = "::before";
      var testProperty       = "font-family";
      var testValue          = "bootstrap-icons !important";
      var hrefFallback       = "/bootstrap-icons.css";
    }
    <meta name="x-stylesheet-fallback-test" content="" class="@testClass" />
    <script>
      var scriptTag  = document.getElementsByTagName('SCRIPT');                      // this tag is "last" when browser gets here
      var metaTag    = scriptTag[scriptTag.length - 1].previousElementSibling;       // ...so meta tag immediately before is the one we want
      var metaStyles = document.defaultView && document.defaultView.getComputedStyle
        ? document.defaultView.getComputedStyle(metaTag, '@testPseudoSelector')      // here is the magic
        : metaTag.currentStyle;
      if (metaStyles && metaStyles['@testProperty'] !== '@testValue')
        document.write('<link rel="stylesheet" href="' + '@hrefFallback' + '" crossorigin="anonymous" />');
    </script>
    

    That is very similar to what the tag helper does, except it also considers the ::before pseudo selector using the getComputedStyle(element, pseudoSelector) override.

    I only need this workaround for one library (bootstrap-icons), but if you find you use it repeatedly, you could refactor it into a custom tag helper, e.g. PseudoSelectorAwareLinkTagHelper.