Next.js
Use TwicPics Next.js Components to get images and videos integration best practices out-of-the-box.
You can find usage examples in our online demo project.
Installation
Add the @twicpics/components
package to your project:
# Using yarn
yarn add @twicpics/components
# Or using npm
npm install @twicpics/components
Setup
If you only want to use the Next.js loader, skip to Next.js Image Loader.
Install TwicPics In Your Next.js Project
This example uses ES module imports, but TwicPics Components is compatible with CommonJS and require
statements.
// _app.js
import { installTwicpics } from "@twicpics/components/react";
import "@twicpics/components/style.css";
installTwicpics({
domain: "https://<your-domain>.twic.pics"
});
export default function MyApp({ Component, pageProps }) {
return (
// your app code
)
}
WARNING: Updating the configuration passed to installTwicpics()
method in watch mode (i.e. when running next dev
) will lead to a install function called multiple times
warning in the browser console. You will need to manually reload the page to apply the new configuration.
Setup Options
Option | Description | Type | Default |
---|---|---|---|
anticipation | TwicPics will lazy-load images by default. To avoid too abrupt a transition with elements appearing into view and then images very obviously loading afterwards, TwicPics will "anticipate" lazy loading by a factor of the actual viewport. This behavior is controlled by this setting. | Number | 0.2 |
domain | This is your very own TwicPics domain. Providing it is mandatory. | String | |
env | Can be debug , offline or production . When set to debug , a gray lightweight svg placeholder that displays its intrinsic dimensions is displayed in place of all medias targeted by their src value. When set to offline , these medias are replaced by a simple placeholder that allows to visualise their display area. | String | "production" |
handleShadowDom | Must be set to true when using TwicComponents within a shadow DOM. | boolean | false |
maxDPR | TwicPics will take the "Device Pixel Ratio" (DPR ) of the current device into consideration when determining the sizes of images to load. By default, it will not take a DPR greater than 2 into consideration. If the DPR of the device is higher than 2 , TwicPics will assume it to be 2 . Using maxDPR , you can lower this limit down to 1 or be more permissive (for instance by setting it to 3 or 4 ). | Number | 2 |
path | Path to prepend to all src attributes. For instance, if path is "some/folder" then a src attribute set to "image.jpg" will be expanded into "some/folder/image.jpg" | String | |
step | To avoid requesting too may variants of the same image, TwicPics will round the width of images to the closest multiple of step. The height will then be computed in order to respect the original aspect ratio. | Integer | 10 |
Usage
Basic Usage
// MyComponent.jsx
import React from 'react'
import { TwicImg } from '@twicpics/components/react'
const YourTemplate = () => <TwicImg src="path/to/your/image" />
export default YourTemplate
Bulk loading with TwicView
By default, <TwicImg>
and <TwicVideo>
will only start loading when they come into the viewport. But sometimes, you may want to load multiple assets in bulk instead of lazy loading them. This is where <TwicView>
comes into play.
The <TwicView>
components eager loads all of his <TwicImg>
and <TwicVideo>
children as soon as it comes into the viewport (depending on your anticipation settings.)
For example, if you're building a carousel, you might want to bulk load all images. In the following code, all three images will be loaded when TwicView
comes into the viewport:
<TwicView>
<TwicImg src="image1.jpg" />
<TwicImg src="image2.jpg" />
<TwicImg src="image3.jpg" />
</TwicView>
Style-Driven Approach
You can style your components using pure CSS with CSS variables.
CSS
.landscape {
--twic-ratio: calc(4 / 3);
}
.portrait {
--twic-ratio: calc(3 / 4);
}
.square {
--twic-ratio: calc(1);
}
.contain {
--twic-mode: contain;
}
.cover {
--twic-mode: cover;
}
.left {
--twic-position: left;
}
.right {
--twic-position: right;
}
.lg {
width: 300px;
}
.md {
width: 150px;
}
.sm {
width: 100px;
}
Template
<div className="landscape">
<TwicImg src="path/to/your/image" />
</div>
<div className="square">
<TwicImg src="path/to/your/image" />
</div>
<div className="portrait">
<TwicImg src="path/to/your/image" />
</div>
<div className="contain left">
<TwicImg src="path/to/your/image" ratio="16/9" />
</div>
<div className="contain right">
<TwicImg src="path/to/your/image" ratio="16/9" />
</div>
<!---
Attributes take precedence over CSS.
In the next example, ratio will 16/9 AND NOT 1 as defined in square css class
--->
<div className="cover square">
<TwicImg src="path/to/your/image" ratio="16/9" />
</div>
Responsive Example
CSS variables also enable you to create responsive designs without hassle.
/* styles.css */
.style-driven {
--twic-ratio: 1.9;
}
@media (min-width: 640px) {
.style-driven {
--twic-mode: contain;
}
}
@media (min-width: 768px) {
.style-driven {
--twic-mode: cover;
--twic-ratio: calc(4 / 3);
}
}
@media (min-width: 1024px) {
.style-driven {
--twic-ratio: calc(16 / 9);
}
}
@media (min-width: 1280px) {
.style-driven {
--twic-ratio: calc(21 / 9);
}
}
@media (min-width: 1536px) {
.style-driven {
--twic-ratio: calc(36 / 9);
}
}
Now, your template can feature a single component that follows your CSS directives and behave responsively.
// MyComponent.jsx
import 'style.css'
export default function () {
return <TwicImg className="style-driven" src="path/to/your/image" />
}
Working with ratio="none"
This is particularly useful when creating hero banner. You can use it to specify an height of your image or vieo while preserving its natural aspect ratio and optimizing your Cumulative Layout Shift (CLS) metric.
When using ratio="none"
, you are responsible for properly sizing the component.
/* style.css */
.hero-image {
height: 500px;
}
@media (min-width: 1024px) {
.hero-image {
height: 300px;
width: 100%;
}
}
// MyComponent.jsx
<TwicImg src="path/to/your/image" className="hero-image" ratio="none" />
Lifecycle
Passing a callback function to onStateChange
gives access to the loading state of your image or video.
Here are the values the Component will emit (see State Type definition) :
new
: when theimg
orvideo
source has not started loadingloading
: when theimg
orvideo
source is loadingdone
: when theimg
orvideo
source has successfully loadederror
: when an error occurred while loading theimg
orvideo
source
// component.jsx
const [state, setState] = useState(undefined)
const handleStateChange = (stateEvent) => {
// Implement the logic here
const { state } = stateEvent
console.log(`TwicComponent emits a new state`, state)
setState(state)
}
return <TwicImg onStateChange={handleStateChange} src="path/to/your/image" />
Components Properties
TwicImg
This component can be used in place of an img
element.
<TwicImg
src="<path>"
alt="<String>"
anchor="<String>"
bot="<String>"
eager="<boolean>"
focus="<auto|coordinates>"
intrinsic="<String>"
mode="<contain|cover>"
onStateChange="<function>"
position="<css position>"
placeholder="<preview|maincolor|meancolor|none>"
preTransform="<String>"
ratio="<ratio>"
step="<integer>"
transition="<fade|zoom|none>"
transitionDelay="<String>"
transitionDuration="<String>"
transitionTimingFunction="<String>"
/>
Attribute | Description | Type | Default |
---|---|---|---|
alt | alt attribute content | String | based on src |
anchor | Positions the image in both contain and cover mode. Accepted values are top , bottom , left , right , top-left , top-right , bottom-left and bottom-right . position and focus take precedence in contain and cover mode respectively. Please note that anchor is applied after an eventual preTransform . | String | |
bot | A slash-separated list of TwicPics API transformations to be performed for search engine bots. This overrides all other transformations when provided, even if empty (i.e bot="" ). See the TwicPics bot attribute documentation for more information. | String | |
eager | Load the image as soon as the component is mounted. This effectively means disabling lazy loading for this image. | boolean | false |
focus | Sets the focus point in cover mode. focus takes precedence over anchor when both are provided. See the TwicPics focus attribute documentation for more information. Only use this attribute if you need a specific focus point or if you want to leverage smart cropping with focus="auto" : if you only need border-based positionning (top , bottom , left , right , etc), use anchor instead. | String | |
intrinsic | Dimensions in pixels of the original image, formatted <width>x<height> (eg. 1920x1080). It prevents image upscaling and limits the number of generated variants. If using preTransform , you should specify the intrinsic dimensions of the resulting image. Using incorrect values can lead to display issues, see the intrinsic attribute documentation. | String | |
onStateChange | A callback function triggered each time the image loading state is updated. State can be new , loading , done or error . | ( stateEvent: StateEvent ) => void | |
mode | Can be contain or cover and determines if the image fills the area and is cropped accordingly (cover ) or if the image will sit inside the area with no cropping (contain ). | String | cover |
placeholder | Can be preview , meancolor , maincolor or none . See the TwicPics output transformation documentation for more information. Setting will be overridden to none when using zoom transition . | String | preview |
position | Positions the image in contain mode. position takes precedence over anchor when both are provided. Syntax is the same as for CSS position properties background-position and object-position . Only use this attribute if you need precise positionning: if you only need border-based positionning (top , bottom , left , right , etc), use anchor instead. | String | center |
preTransform | A slash-separated list of TwicPics API transformations to be performed before resizing the image (see the TwicPics Manipulation documentation). Note that anchor and focus are applied after preTransform : if you need to specify a specific focus point for your preTransform then it needs to be part of the expression (like preTransform="focus=auto/crop=50px50p" for instance). Be aware that using this option can lead to unexpected results so use with caution! | String | |
ratio | A unitless width/height or width:height value pair (as in 4/3 or 4:3 ) that defines the aspect ratio of the display area. If height is not specified, it is assumed to be 1 . A square area will be created by default. When set to none , ratio is determined based on width and height as computed by the browser following your CSS definitions. The --twic-ratio CSS variable is ignored in this instance. You are responsible for properly sizing the component when ratio="none" . | String | 1 |
src | Path to the image. When not provided, a red lightweight svg placeholder that displays its intrinsic dimensions is displayed in place of the absent image. When env is set to offline , that red lightweight svg is replaced by a simple red placeholder. | String | |
step | See the TwicPics step attribute documentation for more information. | Integer | 10 |
transition | Determines how the image will be revealed once loaded. With a fade in effect (fade ), a zoom effect (zoom ) or without any transition (none ). Unsupported values are handled as fade . | String | fade |
transitionDuration | Duration of the transition effect. | String | 400ms |
transitionTimingFunction | CSS timing function applied to the transition effect. | String | ease |
transitionDelay | Transition delay of the transition effect. | String | 0ms |
TwicVideo
This component can be used in place of a video
element.
<TwicVideo
src="<path>"
anchor="<String>"
bot="<String>"
eager="<boolean>"
focus="<auto|coordinates>"
intrinsic="<String>"
mode="<contain|cover>"
position="<css position>"
placeholder="<preview|maincolor|meancolor|none>"
preTransform="<String>"
ratio="<ratio>"
step="<integer>"
transition="<fade|zoom|none>"
transitionDelay="<String>"
transitionDuration="<String>"
transitionTimingFunction="<String>"
/>
Attribute | Description | Type | Default |
---|---|---|---|
alt | alt attribute content | String | based on src |
anchor | Positions the video in both contain and cover mode. Accepted values are top , bottom , left , right , top-left , top-right , bottom-left and bottom-right . position and focus take precedence in contain and cover mode respectively. Please note that anchor is applied after an eventual preTransform . | String | |
bot | A slash-separated list of TwicPics API transformations to be performed for search engine bots. This overrides all other transformations when provided, even if empty (i.e bot="" ). See the TwicPics bot attribute documentation for more information. | String | |
eager | Load the image as soon as the component is mounted. This effectively means disabling lazy loading for this image. | boolean | false |
focus | Sets the focus point in cover mode. focus takes precedence over anchor when both are provided. See the TwicPics focus attribute documentation for more information. Only use this attribute if you need a specific focus point or if you want to leverage smart cropping with focus="auto" : if you only need border-based positionning (top , bottom , left , right , etc), use anchor instead. | String | |
intrinsic | Dimensions in pixels of the original video, formatted <width>x<height> (eg. 1920x1080). It prevents video upscaling and limits the number of generated variants. If using preTransform , you should specify the intrinsic dimensions of the resulting video. Using incorrect values can lead to display issues, see the intrinsic attribute documentation. | String | |
onStateChange | A callback function triggered each time the video loading state is updated. State can be new , loading , done or error . | ( stateEvent: StateEvent ) => void | |
mode | Can be contain or cover and determines if the video fills the area and is cropped accordingly (cover ) or if the video will sit inside the area with no cropping (contain ). | String | cover |
placeholder | Can be preview , meancolor , maincolor or none . See the TwicPics output transformation documentation for more information. Setting will be overridden to none when using zoom transition . | String | preview |
position | Positions the video in contain mode. position takes precedence over anchor when both are provided. Syntax is the same as for CSS position properties background-position and object-position . Only use this attribute if you need precise positionning: if you only need border-based positionning (top , bottom , left , right , etc), use anchor instead. | String | center |
preTransform | A slash-separated list of TwicPics API transformations to be performed before resizing the video (see the TwicPics Manipulation documentation). Note that anchor and focus are applied after preTransform : if you need to specify a specific focus point for your preTransform then it needs to be part of the expression (like preTransform="focus=auto/crop=50px50p" for instance). Be aware that using this option can lead to unexpected results so use with caution! | String | |
ratio | A unitless width/height or width:height value pair (as in 4/3 or 4:3 ) that defines the aspect ratio of the display area. If height is not specified, it is assumed to be 1 . A square area will be created by default. When set to none , ratio is determined based on width and height as computed by the browser following your CSS definitions. The --twic-ratio CSS variable is ignored in this instance. You are responsible for properly sizing the component when ratio="none" . | String | 1 |
src | Path to the video. When not provided, a red lightweight svg placeholder that displays its intrinsic dimensions is displayed in place of the absent video. When env is set to offline , that red lightweight svg is replaced by a simple red placeholder. | String | |
step | See the TwicPics step attribute documentation for more information. | Integer | 10 |
transition | Determines how the video will be revealed once loaded. With a fade in effect (fade ), a zoom effect (zoom ) or without any transition (none ). Unsupported values are handled as fade . | String | fade |
transitionDuration | Duration of the transition effect. | String | 400ms |
transitionTimingFunction | CSS timing function applied to the transition effect. | String | ease |
transitionDelay | Transition delay of the transition effect. | String | 0ms |
Loading State Values
Union type for all possible image or video loading state.
type State = `error` | `done` | `loading` | `new`
new
: when theimg
orvideo
source has not started loadingloading
: when theimg
orvideo
source is loadingdone
: when theimg
orvideo
source has successfully loadederror
: when an error occurred while loading theimg
orvideo
source
State Change Event
Data type passed as parameter to onStateChange
function.
export type StateEvent = {
target: TwicImg | TwicVideo
state: State
}
CSS Variables
List of variables that can be used to configure your components using pure CSS.
<selector > {
--twic-ratio: <ratio>;
--twic-mode: <contain|cover>;
--twic-position: <css position>;
--twic-transition-delay: <string>;
--twic-transition-duration: <string>;
--twic-transition-timing-function: <string>;
}
Each CSS variable corresponds to one of the components attributes listed in the Components Properties section. If present, the attribute takes precedence over the corresponding CSS variable.
Variable | Description | HTML Attribute | Default |
---|---|---|---|
--twic-mode | Can be contain or cover and determines if the image fills the area and is cropped accordingly (cover ) or if the image will sit inside the area with no cropping (contain ). | mode | cover |
--twic-position | Only useful in contain mode. Locates the image inside the area. Syntax is the same as for CSS position properties like background-position or object-position. Useful values are top , bottom , left , right , left top , left bottom and so on. | position | center |
--twic-ratio | Floating point value corresponding to a unitless width/height ratio (as in calc(4/3) or 1.333 ). Ratio will correspond to a square area by default. | ratio | 1 |
--twic-transition-delay | Transition delay of the transition effect. | transitionDelay | 0ms |
--twic-transition-duration | Duration of the transition effect. | transitionDuration | 400ms |
--twic-transition-timing-function | CSS timing function applied to the transition effect. | transitionTimingFunction | ease |
Next.js Image Loader
If it does not exist, create a .env
file at the root of your project.
Set the NEXT_PUBLIC_TWICPICS_DOMAIN
environment variable to your own Twicpics domain:
NEXT_PUBLIC_TWICPICS_DOMAIN="https://<your-domain>.twic.pics/"
Basic Usage
The example below shows how to use the TwicPics loader:
// MyComponent.jsx
import Image from 'next/image'
import { twicpicsLoader } from '@twicpics/components/next'
const MyImage = (props) => {
return (
<Image
loader={twicpicsLoader}
src="image.jpg"
alt="Image alt description"
width={500}
height={500}
/>
)
}
Please note that this will stretch the image to fit the specified size, which might not match the desired aspect ratio.
For easier aspect ratio management, consider using the <TwicImg>
component (see Setup). This will also give you access to all TwicPics features like smart cropping, automatic next-gen formats, and more.
Using Placeholders
This is only supported from Next.js 13.
The Next Image component allows to implement low quality image placeholders by setting the placeholder
prop to blur
.
When doing so, we need to set the blurDataURL
prop. This prop expects the URL of a Base64-encoded image. TwicPics provides a twicpicsPlaceholder
helper that returns such URL.
import Image from 'next/image'
import { twicpicsLoader, twicpicsPlaceholder } from '@twicpics/components/next'
// In this example, we're generating the placeholder URL on server-side
export async function getServerSideProps() {
const data = {
src: `image.jpg`
}
datas.blurDataURL = await twicpicsPlaceholder('image:football.jpg')
return {
props: {
data
}
}
}
const MyImage = ({ data }) => {
return (
<Image
loader={twicpicsLoader}
src={data.src}
placeholder="blur"
blurDataURL={data.blurDataURL}
alt="Image alt description"
/>
)
}
Feedback and support
TwicPics Components are open-source on GitHub. For features requests and bugs, open an issue. The TwicPics team also remains available for support via the live chat (at the bottom right.)