This SVG always shows today's date


For my contact page, I wanted a generic calendar icon to let people view my diary. Calendar icons are almost always a skeuomorph of a paper calendar, but I wondered if I could make it slightly more useful by creating a dynamic icon.

Here it is, an SVG calendar which always display's today's date:

The background image is derived from the Twitter TweMoji Calendar icon - CC-BY.

Text support in SVG is a little awkward, so let me explain how I did this.

SVG supports JavaScript. This will run as soon as the image is loaded.

<svg onload="init(evt)" xmlns="http://www.w3.org/2000/svg"
aria-label="Calendar" role="img" viewBox="0 0 512 512">

Next step is to get the various date strings. I'm using the en-GB locale as that's where I'm based.

<script type="text/ecmascript"><![CDATA[
function init(evt) {
  var time = new Date();
  var locale = "en-gb";

I want to display something like "Sunday 25 FEB" - the locale options allow for short and long names. So you could have "SUN 25 February".

  var DD   = time.getDate();
  var DDDD = time.toLocaleString(locale, {weekday: "long"});
  var MMM = time.toLocaleString(locale,  {month:   "short"});

Finally, we need to add the text on to the image.

  var svgDocument = evt.target.ownerDocument;

  var dayNode = svgDocument.createTextNode(DD);
  svgDocument.getElementById("day").appendChild(dayNode);

  var weekdayNode = svgDocument.createTextNode(DDDD);
  svgDocument.getElementById("weekday").appendChild(weekdayNode);

  var monthNode = svgDocument.createTextNode(MMM.toUpperCase());
  svgDocument.getElementById("month").appendChild(monthNode);

}
]]></script>

Text positioning is relatively simplistic. An X & Y position which is anchored to the bottom of the text - remember that letters with descenders like g will extend beyond the bottom of the Y co-ordinate. This is also where we set the colour of the text, its size, and a font.

A monospace font makes it easier to predict the layout.

<text id="month"
  x="32" 
  y="164" 
  fill="#fff" 
  font-family="monospace"
  font-size="140px"
  style="text-anchor: left"></text>

A word on anchoring. To centre the anchor, use style="text-anchor: middle"

A quick test shows that this works on all desktop browsers and Android browsers. I've not tested on iPhones or anything more exotic.

Enjoy!



Share this post on…

20 thoughts on “This SVG always shows today's date”

  1. Ade Thompson says:

    I can confirm works as expected on iPhone 🙂

    Very nice implementation, will be using this at some point for sure.

    Reply
  2. says:

    Rather than inserting textnodes, you can use the .textContent property to directly set the text:

    function init(evt) {
    var time = new Date();
    var locale = “en-gb”;
    var date = time.getDate();
    document.getElementById(“day”).textContent = date;

    var weekday = time.toLocaleString(locale, { weekday: “long” });
    document.getElementById(“weekday”).textContent = weekday;

    var month = time.toLocaleString(locale, {month: “short”});
    document.getElementById(“month”).textContent = month.toUpperCase();
    }

    Reply
    1. @edent says:

      The original image is CC-BY. I'm happy for this to be licensed in the same way. As code is not typically licensed with CC, you can think of it as MIT - but I'd consider it too trivial to be worth it ☺️

      Reply
  3. Dean Le says:

    The issue is it uses local phone time. If the phone goes wrong, it's wrongly displaying. Use server time.

    Reply
    1. Chuck says:

      That’s problematic if the server and client are far away from each other. If the client’s clock is wrong, at least this will be consistent!

      Reply
    2. That Guy says:

      Unless you happen to be in the same timezone as the server, this is very likely a big fail.

      Reply
      1. Matt says:

        Server could send the date in UTC, and let the client convert to local time. But then you’re relying on the clients clock again – might as well just get their local time directly.

        Reply
  4. Bryan says:

    You should probably mention that this will only work if the SVG is embedded directly in the HTML, in an iframe or by using the embed tag. This shouldn’t (and likely won’t based off of Chrome 63) work if the SVG is added to the page using an IMG tag.

    Reply
    1. My initial thought would be that this could be a security risk. Glad too see that you’re right – it won’t work as an img tag.

      Reply
    2. says:

      Note that the SVG element was made part of HTML5 and can be inlined with full functionality (and without XML namespace and DTD craziness). You don't need an embed (object, iframe, etc), nor an img element.

      Reply
  5. Eric Andersen says:

    Sorry, I'm still working on the word "skeuomorph." Had to break out the dictionary for that one. Thanks for the new word....

    Reply
  6. Eric Andersen says:

    Sorry, I'm still working on the word "skeuomorph." Had to break out the dictionary for that one. Thanks for the new word....

    Don't mean to sound like a wise a**. I enjoy reading your posts very much, silent most of the time.

    Reply
  7. Andrew McGlashan says:

    That's great, but I think it would be even better if it was done totally with CSS if that is possible.

    Reply
  8. Jonathan Hodgson says:

    Very interesting idea. With JS disabled / not available, it displays an empty calendar. Do you think it would be worth having a fallback to a generic date?

    Reply
  9. Johan says:

    Can anyone explain to me why this one is strange if I'm putting Swedish as local?
    I works perfect on a PC/Mac but on my iPhone using Safari or Crome it will NOT put out the text in Swedish but in some other language I cant understand.

    Reply

Trackbacks and Pingbacks

What links here from around this blog?

What are your reckons?

All comments are moderated and may not be published immediately. Your email address will not be published.Allowed HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong> <p> <pre> <br> <img src="" alt="" title="" srcset="">