diff --git a/packages/pwa-buildpack/src/Utilities/addImgOptMiddleware.js b/packages/pwa-buildpack/src/Utilities/addImgOptMiddleware.js index 9323bbea7b..51bf16ac73 100644 --- a/packages/pwa-buildpack/src/Utilities/addImgOptMiddleware.js +++ b/packages/pwa-buildpack/src/Utilities/addImgOptMiddleware.js @@ -63,11 +63,7 @@ https://github.com/nodejs/node-gyp#installation` const imageUrl = new URL(incomingUrl, backendUrl); debug('imageUrl', imageUrl); - const optParamNames = ['auto', 'format', 'width']; - - const rewritten = new URL( - `https://0.0.0.0/resize/${incomingQuery.width}` - ); + const optParamNames = ['auto', 'format', 'width', 'height']; // Start with the original search params, so // we can preserve any non-imageopt parameters @@ -83,6 +79,24 @@ https://github.com/nodejs/node-gyp#installation` if (incomingQuery.auto === 'webp') { params.set('format', 'webp'); } + + const { width, height } = incomingQuery; + let rewrittenUrl = `https://0.0.0.0/resize/${width}`; + + // If we received height and width we should force crop since our + // implementation of express sharp defaults fit to "outside" if crop + // is falsy. `outside` sizes the image, retaining the aspect ratio + // but may fall "outside" the desired height or width. `cover` + // retains the aspect ratio like `outside` but clips to fit desired + // height and width. + // https://github.com/magento-research/express-sharp/blob/develop/lib/transform.js#L23 + // https://sharp.pixelplumbing.com/en/stable/api-resize/ + if (height) { + rewrittenUrl += `/${height}`; + params.set('crop', true); + } + + const rewritten = new URL(rewrittenUrl); rewritten.search = params.toString(); debug({ rewritten }); diff --git a/packages/venia-concept/src/components/Gallery/item.js b/packages/venia-concept/src/components/Gallery/item.js index 939b0fac58..7932269b8a 100644 --- a/packages/venia-concept/src/components/Gallery/item.js +++ b/packages/venia-concept/src/components/Gallery/item.js @@ -6,8 +6,10 @@ import classify from 'src/classify'; import { transparentPlaceholder } from 'src/shared/images'; import defaultClasses from './item.css'; +// The placeholder image is 4:5, so we should make sure to size our product +// images appropriately. const imageWidth = '300'; -const imageHeight = '372'; +const imageHeight = '375'; const ItemPlaceholder = ({ children, classes }) => (