Generating realistic t-shirt mock-ups with CSS mix-blend-mode and Puppeteer
Tags: css, puppeteer, showdev, tutorial
Published: 2020-01-15 15:06:49

[Puppeteer](https://github.com/puppeteer/puppeteer) is an awesome tool with which you are able to load a webpage in a headless browser, interact with it, take screenshots and more. There are a few articles out there demonstrating how to use it to [take screenshots of web pages](https://dev.to/benjaminmock/how-to-take-a-screenshot-of-a-page-with-javascript-1e7c), [generate PDFs](https://dev.to/damcosset/generate-a-pdf-from-html-and-back-on-the-front-5ff5) and [other useful things](https://dev.to/damcosset/a-command-line-application-scraping-dev-to-with-puppeteer-149k). It’s articles like these that gave me the idea to use Puppeteer to generate product images for t-shirt designs on [Forked](https://forkedmerch.com). This is a slightly different use case from what I have seen written about, so I thought it was worth sharing.

[Forked](https://forkedmerch.com) is a site where you can create t-shirt designs using HTML & CSS. We want to generate a mock-up image for a t-shirt design as soon as one is published. The mock-up should feel as realistic as possible, with the design blended with highlights and lowlights of the fabric. There are 47 t-shirt colours to choose from and we need to generate mock-ups for any of these. I wanted to find a method for generating these images that wouldn’t mean exporting a base image for every colour. I also wanted a solution that would scale well when adding new products.

![A t-shirt design with the text ‘But does it scale?’](https://thepracticaldev.s3.amazonaws.com/i/lzjwcltabpz489ngljc6.jpg)

## In Photoshop

Unlike me, Forked’s designer Will can use Photoshop properly. In order to achieve a realistic slightly creased effect, he stacked a series of layers and applied various blend modes and levels of opacity. These layers are:

1. A t-shirt shape with a solid base colour at 100% opacity
2. The t-shirt design at 100% opacity
3. A white t-shirt with colour burn blend mode applied at 30% opacity
4. A highlight layer with soft light blend mode applied at 10% opacity
5. A white t-shirt with multiply blend mode applied at 100% opacity
6. A black t-shirt with screen blend mode applied at 100% opacity

![An exploded view of the layers used to compose the t-shirt mock-up](https://thepracticaldev.s3.amazonaws.com/i/grv1bzy1upa2kj87ddqb.jpg)

## In CSS

To replicate this in a web page, the stacking of the layers can be achieved using absolute positioning. With Puppeteer we can capture a screenshot of the page either as a PNG with a transparent background or as a JPEG with a background colour burned in.

### Making it realistic

I was aware of blend mode support in CSS but had never actually used it. Support is not perfect (no Edge for example) but in our case that’s not a concern as we are only loading this page in Puppeteer, which is headless Chromium. `mix-blend-mode` accepts values including `color-burn`, `soft-light`, `multiply` and `screen`. I applied `mix-blend-mode` and `opacity` using the same values as Will had in Photoshop to achieve the same realistic effect.


### Making the colour dynamic

One problem remained with this method, layer 1 requires a static image for every colour we want to support. In Photoshop it is straight forward to change the colour of a raster layer like this, but sadly not the case in the browser. To solve this we changed layer 1 to a ‘stencil’ layer, with a ‘cut out’ transparent shirt shape in the centre and a solid background colour around it. Underneath this we set the background colour of the document body with CSS so it would show through the stencil. This means we can now dynamically set the t-shirt colour with CSS when we generate the image. We do however lose the ability to dynamically set the background colour around the t-shirt, as this is burned into the stencil layer. This seems like a decent trade off, 47 t-shirt colours vs 2 background colours is a no brainer.

![An exploded view of the stencil approach to dynamic t-shirt colour base layer](https://thepracticaldev.s3.amazonaws.com/i/8an5zwk4sj53ybwsslae.jpg)

## Conclusion

Eventually we decided to choose a slightly different stock t-shirt image but the method remains the same as above. It’s not a perfect solution because we will need to generate a new image for each background colour, but the important thing is we can generate a mock-up for any colour t-shirt. Hopefully this method will work for other products* if/when we add them to [Forked](https://forkedmerch.com). 👕 

![A t-shirt design that reads ‘Thanks for reading’ with a thumbs up graphic that changes colour](https://thepracticaldev.s3.amazonaws.com/i/pfu756ccdz7c95d7dfi3.jpeg)

*laptop sleeve anyone?