cssannotationsdefinitionepubkindle

How to mimic Amazon's Word Wise anotation feature


When enabled, eInk Kindles and some Kindle apps display definitions above less frequently used words. For example:

Kinde Word Wise screenshot

I tried to emulate this feature with <ruby> tags, but it didn't work when the definition was longer than the defined word. Also, if you look closer at the screen capture, you'll notice that there's also a vertical bracket(?) above each word that matches its length.

What would be the best approach to mimic this layout using only HTML5 and CSS?


Solution

  • So here's a basic version of how I would do this, although I can see some trouble in specific scenarios where the explanations of side-by-side words overlap.

    First I wrapped each word inside a span element and added a data-tooltip attribute with the word explanation. I styled using pseudo elements so that the explanations are absolutely positioned at the top of each word and added a border-top with another pseudo element on the word-to-be-explained to fake the arrow tip.

    CSS:

    body {
      font-size:22px;
    }
    [data-tooltip] {
      position:relative;
      display:inline-block;
      margin-top:20px;
      border-top:1px solid red;
    }
    [data-tooltip]:before {
      content:attr(data-tooltip);
      font-size:12px;
      position:absolute;
      display:inline-block;
      white-space:nowrap;
      /* left:0; */
      margin-top:-20px;
    }
    [data-tooltip]:after {
      content:"";
      display:block;
      width:6px;
      height:6px;
      border-top:1px solid red;
      border-right:1px solid red;
      transform:rotate(-45deg);
      position:absolute;
      left:50%;
      margin-left:-3px;
      top:-4px;
      background:#fff;
    }
    [data-tooltip].left:before {
      left: 0 !important;
    }
    [data-tooltip].right:before {
      right: 0 !important;  
    }
    [data-tooltip].center:before {
      left: 50% !important;
      transform:translateX(-50%);
    }
    

    Additionally, using Javascript, I took the length of each paragraph (assumed all have same width) and create an if statement for the 3 following scenarios: - the word-to-be-explained is before the first 1/3 of the paragraph length - the word-to-be-explained is after the 2/3 of the paragraph length - the word-to-be-explained is between the two above statements ... and adjusted the explanation accordingly by applying classes left, right or center accordingly.

    Javascript

    $(window).on('load resize', function() {
        pw = $('p').first().width();
      $('[data-tooltip]').each(function() {
        pos = $(this).offset().left;
        if (pos < pw/3) {
        console.log('run');
            $(this).removeClass().addClass('left');
        } else if (pos > pw*2/3) {
            $(this).removeClass().addClass('right');
        } else if ((pos > pw/3) && (pos < pw*2/3)) {
            $(this).removeClass().addClass('center');
        }
      })
    })
    

    Here is a working fiddle: https://jsfiddle.net/fgnp07ty/1/

    In case where explanations of two words that are side-by-side are too long and overlap, you would have to either limit explanation width to the word length and add ellipsis at the end (...) - I would go with this solution, or calculate explanation lengths and adjust accordingly - this is too much tbh.