yiibu

research + design

Bento

Beyond responsive images

bento logo

Hello
Bento…

Bento is a server-side (PHP), content adaptation library hack that enables designers and developers to adapt web content based on actual device features. We primarily built Bento (as a reference implementation) to address the frequent performance issues caused by client-side adaptation. There are however many of opportunities to use Bento more creatively: to tweak information flow, conditionally load optional assets, or art direct images for multiple screen sizes.

Bento uses the server to adapt content before its delivered to the device. This enables delivery of more appropriate markup structures on initial load, and can also help reduce page weight by delivering the most device/feature appropriate scripts and images.

Bento can be used to replace all manner of common client-side adaptations such as:

Reminder: Emerging specifications such as flex-box will eventually reduce (although not entirely eliminate) the need for this kind of structural adaptation.

Using Bento doesn't of course prevent you from also using client-side scripts to deliver just-in time layout tweaks, implement social media widgets or deliver advertising. In fact, it should speed loading/rendering of all those things given that the browser isn't also busy processing content adaptations.

How it works

Bento consists of three components:

Unfortunately Bento currently requires well-formed XHTML (yes, that would also include XHTML5?!) as the native XML/HTML parsers in PHP proved a bit too opinionated for any of our less structured markup. As a result all HTML entities not supported in XML must be encoded as numbers rather than names, for example … (ellipsis) must be encoded as … (complete conversion references are available via Google).

You may also notice that Bento uses XPATH selectors instead of the more popular CSS selectors. This was simply a pragmatic decision based on what was easiest to implement and more importantly more performant with PHP, which happens to have a relatively fast XML/XPATH library, but not an equivalent CSS selector library. We also chose to implement Bento on the server rather than the client for performance reasons; to avoid having to perform any significant DOM manipulation on the client or incur any unnecessary HTTP requests over (increasingly mobile) networks.

Ideally (...warning: blue sky thinking here...) this kind of adaptation would happen natively in the browser (client-side, before any pre-parsing, and not via JavaScript) and use CSS selectors instead of XPATH.

Important: Bento is hack a for demonstration purposes, and should not (as it stands today) be used on any real-world projects. We're posting it in the hope that it may serve as mild inspiration for someone tackling that 'responsive images' problem or a browser engineer playing 'what-if'.

Bento is a the result of hacking on various ideas (good and bad) around content adaptation for the past few years and should only be considered a prototype at this stage. Play with it, fork it, experiment with it – and for the love of the web, please come up with something better.

A Basic Example

This page is a (very) basic example of what is possible with Bento. Please have a look at the file defined in the href of the <link rel="adaptation"> tag while reading the rest of this page. It also helps to use a desktop browser and resize your browser window to immediately see the results. Although it also works on mobile devices, you will not be able to compare the results as easily.

<switch>
  <case feature="(min-width:640px)">
    <adapt select="//*[@id='example']" action="replace">    </adapt>
  </case>
</switch>

Supported Actions

Actions supported within <adapt> tags include remove, replace, relocate, prepend, append and transform the latter of which enables XSL transformations, while the other actions all perform basic DOM manipulation on selected element(s) of a document.

Remove

Does exactly what it says, removes the selected element(s) from the document.

<adapt select="//*[@id='remove']/p/a[@href]" action="remove" />

Replace

Replaces the selected element(s) with the content supplied within the <adapt> tag.

<adapt select="//*[@id='replace']" action="replace">
  <aside>
    <figure>
      <img src="images/over640.png"/>
      <figcaption>A basic example over 640 pixels.</figcaption>
    </figure>
  </aside>
</adapt>

Relocate

Relocates the select element(s) before (or after) the specified element(s). The example below shows an element being relocated 'before' the specified element, to relocate after the specified element simply change the 'before' attribute to 'after'.

<adapt select="//*[@class='after']" action="relocate" before="//*[@class='before']" />

Append/Prepend

Appends or prepends (depending on the action specified) the content supplied within the <adapt> tag to the selected element(s).

<adapt select="//*[@id='append']/p" action="append">
  <p>This has been appended over 640 pixels.</p>
</adapt>

Transform

Transforms the selected element(s) based on the specified XSL stylesheet. This action can be particularily useful if you have a number of elements (i.e. <img>) which need to be adapted based on specific rules (i.e. img.lrg.png, img@2x.png, img_hdpi.png, etc).

<adapt select="//*[@id='transform']/img" action="transform" stylesheet="transform.xslt" />

Questions + Comments

If you have any questions or comments please post them to this post on Google+ or the issues area on Github.

Again, Bento is a the result of hacking on various ideas (good and bad) around content adaptation for the past few years (see Muddling through the mobile web and Adaptation) and should only be considered a prototype at this stage. Play with it, fork it, experiment with it – and for the love of the web, please come up with something better.