hn/hidpi

Drop-in HiDPI solution. No new view helpers or workflow required. No JavaScript hacks. Just a few assumptions.

Installs: 1 513

Dependents: 1

Suggesters: 0

Security: 0

Type:typo3-cms-extension

v2.0.0 2021-02-02 08:42 UTC

This package is auto-updated.

Last update: 2021-03-30 09:07:05 UTC


README

Packagist Version Packagist Packagist Packagist Build status

Drop-in HiDPI solution for TYPO3

This extension will extend/override typo3's default view helpers and add srcset support. The difference to other solutions is that there is absolute no further set-up required other than installing this extension.

How to use it

Just install the extension and you are all set.

<f:image image="{image}" width="100" />

will result in

<img src="/normal/image.jpg" width="100" height="100" srcset="/hidpi/image.jpg 1.7321x" />

You just need to make sure that the normal image isn't already way to big for the 1x variant.

Read more about how this works and why i use 1.7321x as a scaling factor in the "how does it work?" section.

How to not use it

You can disable the implementation on a per case base by setting the right options. Here are some examples:

<f:image image="{image}" hidpi="{enable: 0}" />
<f:media file="{image}" hidpi="{enable: 0}" />
<f:media file="{image}" additionalConfig="{hidpi: {enable: 0}}" />

If you have a lot of problems or problems in areas where you can't easily change the implementation you might need to disable override in the extension configuration. In that case you'll need to manually use the extended ViewHelpers of this extension in your fluid templates.

<html xmlns:hidpi="http://typo3.org/ns/Hn/HiDPI/ViewHelpers" data-namespace-typo3-fluid="true">
    <hidpi:image image="{image}" />
    <hidpi:media file="{image}" />
</html>

how does it work?

Implementation

This extension uses the old srcset specification using the x syntax. This is not only because the support for this format is the best but also because the normally better implementation using sizes is actually worse for some of the assumptions of this extension.

You image tag will look like this:

<img src="/normal/image.jpg" width="100" height="100" srcset="/hidpi/image.jpg 1.7321x" />

A little known detail is that you can omit the 1x in srcset if you provide a normal src which you want to do for maximum compatibility.

Assumptions

This extensions works on a few assumptions. For detailed information look at the documentation of the HiDpiHandler class but here is a short recap:

  • HiDPI is most important for smartphones which means that resolutions above ~1000 pixels wide aren't required. Because of this assumption I don't need to know how the image scales in your responsive design.
  • Large images don't profit as much from HiDPI. This extends the last assumption in that it allows me to simply not include a srcset on images bigger than 1000 pixels.
  • HiDPI images don't require as much quality. Because of this I can massively decrease the quality of the HiDPI image so there is only a ~20% size increase for jpeg's. Other formats (namely png) can't be compressed further so there is no difference there. If the image is bigger than 150kb it will be dropped to prevent giant png's.
  • Pixel perfect scaling isn't required. Because of this assumption I opted to not deliver 2x images which have 4x the pixels. Instead I deliver 3 times the pixels or about factor ~1.73. The reason for this is that this massively decreases filesize and reducing jpeg quality only gets you so far before the color artifacts get noticeable in skies etc. There is a possible fix for this in mozjpeg but for simplicity I used this compromise resolution. Another reason for this is because I don't really know how big the image will really be on the screen so 2x might actually be bigger than the screen.

As you can see there are a lot of assumptions that may or may not match your exact case but the most important aspect is to never create a worse result than without this extension. That's why this extension rather fails to create a srcset than to create a horrible/oversize result. Manual optimization will definitely create better results but this drop-in solution will create good results without any additional work.

Options

There are a few optional options that you can optionally opt to operate.

To set them globally use $GLOBALS['TYPO3_CONF_VARS']['EXTCONF'][$extkey]['options'] either in your main extensions ext_localconf.php or in AdditionalConfiguration.php.

To set them in a single case use the new hidpi="{options}" attribute of the image/media view helper or alternatively using the additionalConfig="{hidpi: {options}}" on the media view helper.

  • enabled: true - can be used to disable handling of the srcset altogether on a per case bases.
  • maxDimension: 1000 - can be used to increase the maximum HiDPI image size.
  • maxFactor: 1.7321 - allows to in-/decrease the HiDPI scale factor. Note that this extensions scales jpeg quality accordingly.
  • minFactor: 1.4142 - allows to in-/decrease the minimum HiDPI scale factor. This comes into play if the image either already is near the maxDimension limit or if the source image (or the crop of it) doesn't have more pixels to to show in the HiDPI variant.
  • maxFileSize: 153600 - this is the limit for the file size. It acts as a failsafe in cases of very detailed images or pngs that just get huge at higher resolutions.

Browser support

Basically every browser in this table: https://caniuse.com/#feat=srcset

I don't respect things like picturefill by default since this is basically progressive enhancement but there are a lot of SignalSlots in the HiDpiHandler so you can modify the output at your will.

Run the tests

This project has some basic tests to ensure that it works in all typo3 versions described in the composer.json. These tests are run by bitbucket and defined in bitbucket-pipelines.yml.

To run them locally, there are some composer scripts provided in this project. Just clone the project, run composer install and then composer db:start, wait a few seconds, then composer test. You can also run composer test -- --filter TestCase to run specific text classes/methods/datasets.

Here is a list of available commands:

  • composer db:start will start a database using a docker command. You don't have to use it if you have a database available but you'll need to define the typo3Database* variables.
  • composer db:stop unsurprisingly stops the database again... and removes it.
  • composer test will run all available tests. If your first run fails then you might want to run cc.
  • composer test:unit will just run the unit tests.
  • composer test:functional will just run the functional tests.
  • composer cc will remove some temp files. If your functional test fail for no apparat reason try this.