Pen Settings

HTML

CSS

CSS Base

Vendor Prefixing

Add External Stylesheets/Pens

Any URLs added here will be added as <link>s in order, and before the CSS in the editor. You can use the CSS from another Pen by using its URL and the proper URL extension.

+ add another resource

JavaScript

Babel includes JSX processing.

Add External Scripts/Pens

Any URL's added here will be added as <script>s in order, and run before the JavaScript in the editor. You can use the URL of any other Pen and it will include the JavaScript from that Pen.

+ add another resource

Packages

Add Packages

Search for and use JavaScript packages from npm here. By selecting a package, an import statement will be added to the top of the JavaScript editor for this package.

Behavior

Auto Save

If active, Pens will autosave every 30 seconds after being saved once.

Auto-Updating Preview

If enabled, the preview panel updates automatically as you code. If disabled, use the "Run" button to update.

Format on Save

If enabled, your code will be formatted when you actively save your Pen. Note: your code becomes un-folded during formatting.

Editor Settings

Code Indentation

Want to change your Syntax Highlighting theme, Fonts and more?

Visit your global Editor Settings.

HTML

              
                <h1>πŸ’πŸ» Browser Emoji Scaling</h1>
<p>An πŸ‘©πŸ»β€πŸ”¬experiment by <a href="https://github.com/ticky">Jessica Stokes</a></p>
<p>Different browsers handle scaling of emoji differently. Mostly this doesn't matter, but if you want to render custom emoji-like characters alongside emoji, you'd want them to match!</p>
<p><strong>Unfortunately</strong>, the relationship between font and emoji size in some browsers is not linear, and thus scaling at one global size is infeasible unless your display size requirements are very narrow!</p>
<p>An emoji πŸ‘©πŸ» at your browser's emoji scale</p>
<p>An emoji <img class="emoji" title="buildkite" alt=":buildkite:" draggable="false" src="https://raw.githubusercontent.com/buildkite/emojis/master/img-buildkite-64/buildkite.png" /> which is image-based, compensated to match your browser as closely as possible</p>
<p>This browser renders emoji at <span id="browser-info">?</span>% text size at 16px.</p>
<h2>πŸ€” How do browsers compare?</h2>
<ul>
  <li><strong>macOS</strong>
    <ul>
      <li><strong>Safari</strong>: Emoji are ~1.3125em wide and tall, with a little bit of spacing, vs 16px text</li>
      <li><strong>Chrome</strong>: Emoji are 1.0em wide and tall, with no spacing whatsoever, vs 16px text</li>
      <li><strong>Firefox</strong>: Emoji are 1.0em wide and tall, vs 16px text</li>
    </ul>
  </li>
  <li><strong>Windows 10</strong>
    <ul>
      <li><strong>Chrome</strong>: Emoji are ~1.38em wide and tall, with a little bit of spacing, vs 16px text</li>
      <li><strong>Edge</strong>: Emoji are ~1.38em wide and tall, with a little bit of spacing, vs 16px text</li>
    </ul>
    (It looks like Windows 10 browsers are all using native text rendering, which is nice!)
  </li>
</ul>
<h2>πŸ™‹πŸΌβ€β™‚οΈ How's it calculated?</h2>
<p>We measure the emoji against a string which matches the width we expect an emoji to be at 1em. We then adjust the scale of the custom emoji to match by setting CSS :root variables!</p>
<h3>πŸ“ How accurate is this?</h3>
<p>It's accurate... <strong>but only for a single font size at a time</strong>! In some browsers emoji sizes are scaled in a non-linear fashion against font sizes. This means we'd either need to recalculate scales for every emoji, or just defer to something that <em>mostly</em> works!</p>
<p>Here are the emoji and our test string, all lined up, in your browser;</p>
<p style="font-family: Times, 'Times New roman', serif; text-align: center">Hi <span style="font-family: Times, 'Times New roman', serif;outline: 1px dotted red">πŸ‘©</span> there<br/>
<span>Hi <span style="font-family: Times, 'Times New roman', serif; outline: 1px dotted orangered"><img class="emoji" title="buildkite" alt=":buildkite:" draggable="false" src="https://raw.githubusercontent.com/buildkite/emojis/master/img-buildkite-64/buildkite.png" /></span> there</span><br/>
<span>Hi <span style="font-family: Times, 'Times New roman', serif; outline: 1px dotted orangered">J!i</span> there</span></p>
<p>And here are the same emoji, inside a paragraph with a font size of 2.5em;</p>
<p style="font-size: 2.5em; text-align: center">Hi <span style="font-family: Times, 'Times New roman', serif; font-family: Times, 'Times New roman', serif;outline: 1px dotted red">πŸ‘©</span> there<br/>
<span>Hi <span style="font-family: Times, 'Times New roman', serif; outline: 1px dotted orangered"><img class="emoji" title="buildkite" alt=":buildkite:" draggable="false" src="https://raw.githubusercontent.com/buildkite/emojis/master/img-buildkite-64/buildkite.png" /></span> there</span><br/>
<span>Hi <span style="font-family: Times, 'Times New roman', serif; outline: 1px dotted orangered">J!i</span> there</span></p>
<p>The two emoji should match the proportions specified above, relative to the text (you can whip open the web inspector to check, if you'd like!)</p>
<h2>πŸ“ Conclusion</h2>
<p>This didn't work out, which is a shame! I'd have loved to get this wired up into something useful, but I guess it's just not a sustainable approach!</p>
<p>The more I experiment with emoji handling, the more I realise it's something <em>I shouldn't be doing myself!</em></p>
              
            
!

CSS

              
                :root {
  --custom-emoji-multiplier: 1.25em;
  --custom-emoji-margin: .05em;
}

.emoji {
  width: var(--custom-emoji-multiplier);
  height: var(--custom-emoji-multiplier);
  margin: 0 var(--custom-emoji-margin);
  vertical-align: -.2em;
}

body {
  color: #515151;
  background-color: #fbfbfb;
  font-family: -apple-system, BlinkMacSystemFont, sans-serif;
  max-width: 600px;
  padding: 0 1em;
  margin: 0 auto;
}

a:link, a:visited {
  color: #893ff4;
  text-decoration: none;
}

              
            
!

JS

              
                const EMOJI = "πŸ‘©";
const TEXT = "J!i";

const rootStyles = Array.prototype.find.call(document.querySelector('style').sheet.cssRules, (cssrule) => cssrule.selectorText === ':root').style;

function get_string_width(string) {
  const span = document.createElement('span');
  span.appendChild(document.createTextNode(string));
  span.style.fontFamily = "Times, 'Times New roman', serif";
  document.body.appendChild(span);
  const { width } = span.getBoundingClientRect();
  document.body.removeChild(span);
  return Math.round(width);
}

const emoji_width = get_string_width(EMOJI);
const text_width = get_string_width(TEXT);

console.log(emoji_width, text_width);

const multiplier = (emoji_width / text_width);

const browser_info = document.getElementById("browser-info");
browser_info.innerText = Math.round(multiplier * 100);
browser_info.title = `${multiplier}em`;

const margin = parseFloat(rootStyles.getPropertyValue('--custom-emoji-margin'));

console.log();
rootStyles.setProperty('--custom-emoji-multiplier', `${multiplier - margin * 2}em`);

              
            
!
999px

Console