Skip to content

Commit

Permalink
Fix placeholder=blur inside <noscript> (#27311)
Browse files Browse the repository at this point in the history
We shouldn't be setting `placeholder=blur` styles when JS is disabled because we'll have no way to know when the image is loaded and it will be stuck in blur permanently as mentioned in [this comment](#19052 (comment)).

This PR avoids blur styles on the `<noscript>` version of the image.
  • Loading branch information
styfle committed Jul 20, 2021
1 parent ddef873 commit 5cd37d9
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 5 deletions.
10 changes: 5 additions & 5 deletions packages/next/client/image.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -458,16 +458,16 @@ export default function Image({

objectFit,
objectPosition,

...(placeholder === 'blur'
}
const blurStyle =
placeholder === 'blur'
? {
filter: 'blur(20px)',
backgroundSize: objectFit || 'cover',
backgroundImage: `url("${blurDataURL}")`,
backgroundPosition: objectPosition || '0% 0%',
}
: undefined),
}
: {}
if (layout === 'fill') {
// <Image src="i.png" layout="fill" />
wrapperStyle = {
Expand Down Expand Up @@ -607,7 +607,7 @@ export default function Image({
setRef(img)
handleLoading(img, srcString, placeholder, onLoadingComplete)
}}
style={imgStyle}
style={{ ...imgStyle, ...blurStyle }}
/>
{priority ? (
// Note how we omit the `href` attribute, as it would only be relevant
Expand Down
14 changes: 14 additions & 0 deletions test/integration/image-component/default/test/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -673,6 +673,8 @@ describe('Image Component Tests', () => {
const html = await renderViaHTTP(appPort, '/blurry-placeholder')
const $html = cheerio.load(html)

$html('noscript > img').attr('id', 'unused')

expect($html('#blurry-placeholder')[0].attribs.style).toContain(
`background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='400' height='400' viewBox='0 0 400 400'%3E%3Cfilter id='blur' filterUnits='userSpaceOnUse' color-interpolation-filters='sRGB'%3E%3CfeGaussianBlur stdDeviation='20' edgeMode='duplicate' /%3E%3CfeComponentTransfer%3E%3CfeFuncA type='discrete' tableValues='1 1' /%3E%3C/feComponentTransfer%3E%3C/filter%3E%3Cimage filter='url(%23blur)' href='data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAMDAwMDAwQEBAQFBQUFBQcHBgYHBwsICQgJCAsRCwwLCwwLEQ8SDw4PEg8bFRMTFRsfGhkaHyYiIiYwLTA+PlT/wAALCAAKAAoBAREA/8QAMwABAQEAAAAAAAAAAAAAAAAAAAcJEAABAwUAAwAAAAAAAAAAAAAFAAYRAQMEEyEVMlH/2gAIAQEAAD8Az1bLPaxhiuk0QdeCOLDtHixN2dmd2bsc5FPX7VTREX//2Q==' x='0' y='0' height='100%25' width='100%25'/%3E%3C/svg%3E")`
)
Expand All @@ -690,6 +692,18 @@ describe('Image Component Tests', () => {
)
})

it('should not use blurry placeholder for <noscript> image', async () => {
const html = await renderViaHTTP(appPort, '/blurry-placeholder')
const $html = cheerio.load(html)
const style = $html('noscript > img')[0].attribs.style

expect(style).not.toContain(`background-position`)
expect(style).not.toContain(`background-size`)
expect(style).not.toContain(
`background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='400' height='400' viewBox='0 0 400 400'%3E%3Cfilter id='blur' filterUnits='userSpaceOnUse' color-interpolation-filters='sRGB'%3E%3CfeGaussianBlur stdDeviation='20' edgeMode='duplicate' /%3E%3CfeComponentTransfer%3E%3CfeFuncA type='discrete' tableValues='1 1' /%3E%3C/feComponentTransfer%3E%3C/filter%3E%3Cimage filter='url(%23blur)' href='data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAMDAwMDAwQEBAQFBQUFBQcHBgYHBwsICQgJCAsRCwwLCwwLEQ8SDw4PEg8bFRMTFRsfGhkaHyYiIiYwLTA+PlT/wAALCAAKAAoBAREA/8QAMwABAQEAAAAAAAAAAAAAAAAAAAcJEAABAwUAAwAAAAAAAAAAAAAFAAYRAQMEEyEVMlH/2gAIAQEAAD8Az1bLPaxhiuk0QdeCOLDtHixN2dmd2bsc5FPX7VTREX//2Q==' x='0' y='0' height='100%25' width='100%25'/%3E%3C/svg%3E")`
)
})

it('should remove blurry placeholder after image loads', async () => {
let browser
try {
Expand Down

0 comments on commit 5cd37d9

Please sign in to comment.