skip to Main Content

Goal

I would like to create a web page for templating cards and other objects used in table top board games.
Many games include a sort of "symbol font", i.e. a set of symbols with meaning in the context of the game, which are used inline with text.
Therefore, my end goal is to be able to position several text fields over a background image and include multi-colored custom symbols with that text.

I imagine that what I am attempting requires techniques somewhat similar to whatever is done to support emojis.

I have succeeded in rendering custom symbols in the inner HTML of a <span>.
However, I would like to render the symbols inline with text that can be positioned over an image.
How can this be done?

What I’ve tried

  1. I drew a custom symbol in Inkscape, saved as a 32×32 svg file. It is a half-yellow half-blue circle.

  2. I uploaded the symbol to icomoon and downloaded a font package. Icomoon produces .tff, .svg, and .woff font files. It also produces some example html and css.

  3. I pared down the html and css to a pretty minimal (not)working example:

    demo.html

    <!doctype html>
    <html>
    <head>
        <meta charset="utf-8">
        <title>Symbol font demo</title>
        <link rel="stylesheet" href="style.css">
    </head>
    <body>
        <p>This code</p>
        <xmp>
            <div>
                <span class="my-fontcircle"><span class="path1"></span><span class="path2"></span></span>
            </div>
        </xmp>
        <p>Produces this</p>
        <div>
            <span class="my-fontcircle"><span class="path1"></span><span class="path2"></span></span>
        </div>
        <p>This code</p>
        <xmp>
            <div font-family: "my-font">Let's use our symbol in line: </div>
        </xmp>
        <p>Produces this</p>
        <div font-family: "my-font">Let's use our symbol in line: </div>
    
    </body>
    </html>
    

    style.css

    @font-face {
      font-family: 'my-font';
      src:
        url('fonts/my-font.ttf?81gy7') format('truetype'),
        url('fonts/my-font.woff?81gy7') format('woff'),
        url('fonts/my-font.svg?81gy7#my-font') format('svg');
      font-weight: normal;
      font-style: normal;
      font-display: block;
    }
    
    [class^="my-font"], [class*=" my-font"] {
      /* use !important to prevent issues with browser extensions that change fonts */
      font-family: 'my-font' !important;
      speak: never;
      font-style: normal;
      font-weight: normal;
      font-variant: normal;
      text-transform: none;
      line-height: 1;
    
      /* Better Font Rendering =========== */
      -webkit-font-smoothing: antialiased;
      -moz-osx-font-smoothing: grayscale;
    }
    
    .my-fontcircle .path1:before {
      content: "e900";
      color: rgb(251, 236, 0);
    }
    .my-fontcircle .path2:before {
      content: "e901";
      margin-left: -1em;
      color: rgb(0, 129, 255);
    }
    

The result looks like this:


enter image description here


As we can see, the symbol shows up when we use the css class method, but it doesn’t render in text.
How can we make the symbol show up inline with text?

2

Answers


  1. First off, I’m not sure why you wouldn’t be able to position text over a background image and include multi-colored custom symbols with that text with your initial implementation unless there are some limitations such as HTML escaping where you’d like to use your icons.

    <span> is an inline element, and with a few alignment styles (try inline-flex with justify-content: center; to start) it should work fine. There are loads of resources for centering elements.

    I’ve put together an example with a different icon library:.

    .background {
      background-image: url(http://www.nasa.gov/sites/default/files/thumbnails/image/northseabloom_oli2_2023165_lrg.jpg);
      background-repeat: no-repeat;
      background-position: center;
      
      display: flex;
      flex-direction: column;
      
      height: 200px;
      width: 200px;
    }
    
    .background .text {
      color: white;
    }
    
    .background .icon {
      color: red;
    }
    
    .background .bottom-text {
      margin-top: auto;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/js/all.min.js"></script>
    <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css" rel="stylesheet"/>
    
    <div class="background">
      <p class="text">Hello icons <span class="icon"><i class="fa-solid fa-icons"></i></span>, inline on a background no less!</p>
        <p class="text bottom-text">Hello icons <span class="icon"><i class="fa-solid fa-icons"></i></span>, inline on a background no less!</p>
    </div>

    Your primary issue appears to be that you are using a custom HTML entity, in your example &#xe900;. Am I correct to assume that you expect this to work based on your CSS content: "e900";? My brief research indicates that you need to extend XHTML in order for this to work, which I don’t see in your example. This could be why your icon is not rendering as expected.

    Login or Signup to reply.
  2. If you don’t need to replace common emoji unicode characters (e.g &#x1f600 => smiley) you could write a simple icon injection script.

    /**
    * define your icons
    * as object
    */
    
    let icons = {
      'screaming': "https://camo.githubusercontent.com/26d09c4725b30d28f1d4b28ae161b685fa87d432912f0b7b6dd1e4fbe3cfe2bc/68747470733a2f2f63646e2e6a7364656c6976722e6e65742f6e706d2f407376676d6f6a692f6e6f746f40302e322e302f7376672f31463633312e737667",
      "pleading": "https://camo.githubusercontent.com/dbb026248af889b4cfd2c8bfde4252958b18db090e30ae0e832bbf17cef35216/68747470733a2f2f63646e2e6a7364656c6976722e6e65742f6e706d2f407376676d6f6a692f7477656d6f6a6940322e302e302f7376672f31463937412e737667"
    }
    
    /**
    * query icon placeholders
    * and inject images as defined in object
    */
    let iconsInline= document.querySelectorAll('[data-icon]')
    iconsInline.forEach(icn=>{
      let type = icn.dataset.icon;
      let img = document.createElement('img');
      let src = icons[type];
      img.src = src;
      img.classList.add('img-emoji', `img-emoji-${type}`)
      icn.append(img)
      
    })
    body{
      font-size:8vmin;
    }
    
    [data-icon]{
      display:inline-block;
      height:1em;
      width:1em;
      /** adjust baseline alignment */
      transform: translateY(0.13em);
    }
    <p><span data-icon="pleading"></span> One morning, when Gregor Samsa woke from <span data-icon="pleading"></span> troubled dreams, he found himself transformed in his bed into a <span data-icon="screaming"></span> horrible vermin.</p>

    How it works

    You’re defining an object containing all symbol sources and their identifier:

    let icons = {
      'screaming': "icon1.svg",
      'laughing': "icon2.svg",
    }
    

    Similar to fontAwesome and other icon libray APIs you can specify the icon type by setting a readable/self-explanatory identifier for the placeholder element.

    <span data-icon="screaming"></span>
    

    In this case I’m using a data attribute instead of a class name to avoid class name conflicts and the need of prefixing (e.g. fa-icon-mame).

    Now we can replace the placeholders with the actual icons:

    let iconsInline= document.querySelectorAll('[data-icon]')
    iconsInline.forEach(icn=>{
      let type = icn.dataset.icon;
      let img = document.createElement('img');
      let src = icons[type];
      img.src = src;
      img.classList.add('img-emoji', `img-emoji-${type}`)
      icn.append(img)
    })
    

    You could also adapt this approach to inject inline SVGs.
    However you might run into troubles if your icons contain gradients, masks or clip-paths.
    To circumvent these problems you could use
    Danny ‘365CSI’ Engelman’s <load-file> native web component to append your icons as shadow DOM elements.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search