diff --git a/docs/api-reference/next/future/image.md b/docs/api-reference/next/future/image.md index ee395f9618a6..29cb18803a8a 100644 --- a/docs/api-reference/next/future/image.md +++ b/docs/api-reference/next/future/image.md @@ -9,6 +9,7 @@ description: Try the latest Image Optimization with the experimental `next/futur | Version | Changes | | --------- | -------------------------------------------- | +| `v12.3.0` | Changed `alt` property to required. | | `v12.2.4` | Support for `fill` property added. | | `v12.2.0` | Experimental `next/future/image` introduced. | @@ -43,6 +44,7 @@ Compared to `next/image`, the new `next/future/image` component has the followin - Removes `lazyBoundary` prop since there is no native equivalent - Removes `lazyRoot` prop since there is no native equivalent - Removes `loader` config in favor of [`loader`](#loader) prop +- Changed `alt` prop from optional to required ## Known Browser Bugs @@ -175,6 +177,16 @@ The `height` property represents the _rendered_ height in pixels, so it will aff Required, except for [statically imported images](/docs/basic-features/image-optimization.md#local-images) or images with the [`fill` property](#fill). +### alt + +The `alt` property is used to describe the image for screen readers and search engines. It is also the fallback text if images have been disabled or an error occurs while loading the image. + +It should contain text that could replace the image [without changing the meaning of the page](https://html.spec.whatwg.org/multipage/images.html#general-guidelines). It is not meant to supplement the image and should not repeat information that is already provided in the captions above or below the image. + +If the image is [purely decorative](https://html.spec.whatwg.org/multipage/images.html#a-purely-decorative-image-that-doesn't-add-any-information) or [not intended for the user](https://html.spec.whatwg.org/multipage/images.html#an-image-not-intended-for-the-user), the `alt` property should be an empty string (`alt=""`). + +[Learn more](https://html.spec.whatwg.org/multipage/images.html#alt) + ## Optional Props The `` component accepts a number of additional properties beyond those which are required. This section describes the most commonly-used properties of the Image component. Find details about more rarely-used properties in the [Advanced Props](#advanced-props) section. diff --git a/packages/next/client/future/image.tsx b/packages/next/client/future/image.tsx index 3031fcd7b9de..30031cf1055d 100644 --- a/packages/next/client/future/image.tsx +++ b/packages/next/client/future/image.tsx @@ -100,9 +100,10 @@ function isStaticImport(src: string | StaticImport): src is StaticImport { export type ImageProps = Omit< JSX.IntrinsicElements['img'], - 'src' | 'srcSet' | 'ref' | 'width' | 'height' | 'loading' + 'src' | 'srcSet' | 'ref' | 'alt' | 'width' | 'height' | 'loading' > & { src: string | StaticImport + alt: string width?: number | string height?: number | string fill?: boolean @@ -116,7 +117,7 @@ export type ImageProps = Omit< onLoadingComplete?: OnLoadingComplete } -type ImageElementProps = Omit & { +type ImageElementProps = Omit & { srcString: string imgAttributes: GenImgAttrsResult heightInt: number | undefined @@ -392,6 +393,11 @@ const ImageElement = ({ img ) } + if (img.getAttribute('alt') === null) { + console.error( + `Image is missing required "alt" property. Please add Alternative Text to describe the image for screen readers and search engines.` + ) + } } if (img.complete) { handleLoading( diff --git a/test/integration/image-future/default/pages/missing-alt.js b/test/integration/image-future/default/pages/missing-alt.js new file mode 100644 index 000000000000..7b48115e4306 --- /dev/null +++ b/test/integration/image-future/default/pages/missing-alt.js @@ -0,0 +1,13 @@ +import React from 'react' +import Image from 'next/future/image' +import testJPG from '../public/test.jpg' + +export default function Page() { + return ( +
+

Missing alt

+ + +
+ ) +} diff --git a/test/integration/image-future/default/test/index.test.ts b/test/integration/image-future/default/test/index.test.ts index cdbe51f5f460..c5b3deb535aa 100644 --- a/test/integration/image-future/default/test/index.test.ts +++ b/test/integration/image-future/default/test/index.test.ts @@ -685,6 +685,16 @@ function runTests(mode) { ) }) + it('should show missing alt error', async () => { + const browser = await webdriver(appPort, '/missing-alt') + + expect(await hasRedbox(browser)).toBe(false) + + await check(async () => { + return (await browser.log()).map((log) => log.message).join('\n') + }, /Image is missing required "alt" property/gm) + }) + it('should show error when missing width prop', async () => { const browser = await webdriver(appPort, '/missing-width') diff --git a/test/integration/image-future/typescript/pages/invalid.tsx b/test/integration/image-future/typescript/pages/invalid.tsx index 85a60daa6773..9de4e34c16fb 100644 --- a/test/integration/image-future/typescript/pages/invalid.tsx +++ b/test/integration/image-future/typescript/pages/invalid.tsx @@ -5,20 +5,34 @@ const Invalid = () => { return (

Invalid TS

- + invalid-src invalid-width + /> invalid-placeholder + /> +

This is the invalid usage

) diff --git a/test/integration/image-future/typescript/pages/valid.tsx b/test/integration/image-future/typescript/pages/valid.tsx index 2bc8a517a95e..3dc5a311f9d4 100644 --- a/test/integration/image-future/typescript/pages/valid.tsx +++ b/test/integration/image-future/typescript/pages/valid.tsx @@ -12,12 +12,14 @@ const Page = () => {

Valid TS

width-and-height-num width-and-height-str { /> quality-str { /> data-protocol placeholder-and-blur-data-url - + no-width-and-height object-src-with-placeholder - - + object-src-with-svg + object-src-with-avif

Example Image Usage

- +
- + ) }