Search code examples
cssfontscross-browsergraceful-degradation

How to fall back gracefully when the content is not available


There are (at least) two ways of showing a bitcoin symbol.

One is to use font awesome and style that if you wish:

.fa-btc {
    font-size: 75%;
    color:#6f42c1;
    opacity: 0.8;
    vertical-align: -5%;
    font-variant: small-caps;
}

The other is to just show the new Unicode character 20BF:

.bitcoin::before {
    font-size: 80%;
    opacity: 0.8;
    vertical-align: 10%;
    content: "\20BF";
}

I like the unicode way better. It's more subtle I guess.

But it doesn't work on Android yet. The Roboto and Nono fonts which apparently do the rendering on Android web browsers don't have it yet.

Note that I am downloading a font for my site which does have the symbol, so I'm perplexed why Android is not using it:

<!--website font-->
<link href="https://fonts.googleapis.com/css?family=Roboto|Roboto+Mono" rel="stylesheet">

What would be a way to detect and display the fa icon in these cases where the unicode isn't available?

Ideally, I'd like to key off of the unicode symbol being available in the font which is actually used, as opposed to just looking at the OS or other things which may or may not coincide with the symbol being available. Finding and using a certain font that has this symbol when I'm on Android OS would be a good answer too. I didn't tag Android because this isn't Android development; that just happened to be the environment that alerted me to the issue.


Solution

  • I combined a couple of answers regarding detecting tofu characters and replacing ::before content , and came up with this.

    • Text-based solution
    • Doesn't need code fix once Android starts working

    $(document).ready(function(){
      var bitcoinSymbolAvailable = document.getElementById('char-to-check').offsetWidth !== document.getElementById('not-renderable').offsetWidth;
      if(!bitcoinSymbolAvailable)
        $('body').append('<style>.bitcoin:before{content:"\\0E3F" !important;}</style>');
    });
    .bitcoin::before {
      font-size: 80%;
      opacity: 0.8;
      vertical-align: 10%;
      content: "\20BF"; /* \0E3F */
    }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    
    <div>
      <img width="200" src="https://img.cinemablend.com/filter:scale/quill/9/a/d/3/5/0/9ad35052cecea0ff468e2f03476d9e8e385add82.jpg?mw=600">
      <h1>But first you must pay me... <span class="bitcoin">1,000,000</span>
    </div>
    
    <div style="position:absolute;visibility:hidden;">
      <span id="char-to-check">&#x20BF;</span>
      <span id="not-renderable">&#xFFFF;</span>
    </div>