Search code examples
javascriptcsspolyfills

CSS ::first-letter drop cap ignores $ symbol. Is there a Polyfill?


I'd like to put a custom style on the $ symbol before a price. The easy way:

<style>.dropcap { doStuff; }</style>
<p><span class="dropcap">$</span>19.95</p>

Problem is that the easy way isn't semantic or accessible. The simple, standards-based approach I'd like to follow is to use ::first-letter {} like so:

<style>p::first-letter { doStuff; }</style>
<p>$19.95</p>

That works fine in most browsers, but Firefox interprets the $ symbol as "punctuation" and ignores the CSS rule. Other modern browsers seem to handle this just fine.

Is there a jQuery / JavaScript polyfill or CSS hack that would let me do this the standards-based way and have it still work in Firefox?

UPDATE: I found a polyfill that seems to do the trick: jquery-fancyletter. Was hoping to also find a Modernizr feature detect but can't find one. Tried writing my own and the damned thing always returns false (even in Chrome where the feature is supported). Would anyone be so kind as to let me know what's wrong with my feature detect?

Modernizr.addTest('dollarFirstLetter', function() {
return Modernizr.testStyles('#modernizr p:first-letter {margin-right:20px;display:block}', function(elem) {
    window.ptag = document.createElement("p");
    ptag.innerHTML = "$39.95";
    elem.appendChild(ptag);
    return window.getComputedStyle(ptag, ":first-letter").marginRight === "20px";
});
});

Solution

  • There isn't a test for this in Modernizr, but if you really needed to use it, you would want to create an element that matches the selector you are wanting, and then check an attribute. If it is the known value, then it works, and if it is an unknown/unwanted value, then it is unsupported.

    For example

    #test_element {
      font-size: 0
    }
    #test_element::first-letter {
      font-size: 10px
    }
    

    with something like the following javascript

    var el = document.createElement('div');
    el.id = 'test_element'
    el.innerHTML = '$';
    document.body.appendChild(el);
    Modernizr.addTest('fullFirstCharacter', el.clientHeight > 0);
    document.body.removeChild(el);
    

    Modernizr has a testStyle method that will handle most of this for you, but the above logic is the concept it is using

    (note that in order to test the actual computed styles of an element, you need to actually append it to the body, and then later remove it).

    @Oriol's way of doing this is what I would highly suggest using, however.