Skip to main content


The <cylindo-viewer> is a web component that can be used to display content create with Cylindo.



The customer id of the customer that owns the product. You can find the customer id in the (Cylindo CMS Settings -> Account number)

Related example


The product's code. You can find the code on the product page in the (Products Product -> Code)

Related example


Controls to show. Combine possible flags. You can decide to hide controls to limit the user's interaction with the viewer or to instead implement your own controls.

Default valueOptions
"ar qr fullscreen zoom indicators"ar qr fullscreen zoom nav indicators

Related example


Format of the viewer's assets. By default, the viewer is using the webp format, which is lower in size than the other formats.

You can try and visualize the impact of this parameter on this page.

Default valueOptions
"webp"webp | jpg | png


Language of the viewer.

You will need to set up the translations for the language you want to use. See our guide on Localization for how to set up translations.

Default valueOptions
"en"Any valid language code


You can hide the zoom progress bar by passing zoom-progress-bar="false" to the cylindo-viewer. The progress bar shows when the tiles of the zoom are loading.

Default valueOptions
"true""true" | "false"


By default, the interaction buttons (such as the fullscreen and zoom buttons) will be hidden after a delay when no interaction is detected. This behavior only applies to non-touch devices, when the viewer is not in focus. These buttons will always be shown on touch devices.

If you don't want the interaction buttons to be hidden, you can set the value to Infinity.

Default valueOptions
3000Any valid number, in milliseconds


By default, the zoom buttons are hidden on mobile. This is because mobile user can use pinch to zoom instead, and save some visual space at the same time. If you still want to show the zoom controls to show on touch devices, you can set this value to true.


The zoom controls will stay hidden if the viewer is less than 345 pixels high, and the nav controls are showed. This is to prevent both controls to overlap.

Default valueOptions
"false""true" | "false"


When a user navigates with arrows, an outline will be displayed around the zoom container. This standard accessibility feature can be disabled by passing this flag.

Default valueOptions
Focus Visible

Focus visible is an important feature for accessibility. We do not recommend passing this flag. You can read more about it in this article.


The presence of the qr-modal-disabled attribute disables the built-in QR code modal. This is useful for implementing custom solutions that require a different QR code handling.

Related example


Pass ignore-unknown-features attribute in order to ignore features that do not exist on the product. This is useful to avoid the regular error fallback viewer behavior. This is recommended for production.

Related example


Quality of the viewer's assets.

If png is passed to the format attribute, the quality will be disabled.

You can try and visualize the impact of this parameter on this page.


Lowering the quality can result in visual artifacts due to compression. If you notice visual artifacts, pass lossless to quality or pass png to the format.

Default valueOptions
"90"Integer from 1 to a 100 or lossless


Color code of the asset background. This parameter only applies when jpg is passed to the format attribute.

Default valueOptions
ffffffHexadecimal color code



This property is read-only. The internal store is used primarily for debugging purposes.


The current set of features for the current product. Features control how the product looks. This can be materials, but also entirely different geometry at times.

This property can be read and written to. It is important to note that you have to update the reference to the object for the changes to be picked up by the viewer, like:

// ⚠️ Bad, this will not work
viewer.features.material = "leather";

// ✅ Good, this will work
viewer.features = { ...viewer.features, material: "leather" };
About declarative features

features is a property and not an attribute on a <cylindo-viewer> instance. This means that you cannot declaratively set features, but instead have to set them in JavaScript. You also cannot use the setAttribute or similar method (jQuery attr) to set features.

This is because features is a complex object and not a string or number. We are working on an additional declarative API for setting feature/options in HTML. However, this API is still in the works and is not yet available.

See our guide on configurating features for more information.


This property is read-only. True if the loaded event has fired since the last src change.

Default valueOptions
N/Atrue, false


The zoom level of the viewer.

Default valueOptions
1Any positive float

Related example


The locales object is used to override the default translations.

See our guide on Localization for how to set up translations.

Related example


When viewing a 3D model with the <cylindo-model>, you can access the underlying <model-viewer> via this property.

The property will only be defined when the active item is a <cylindo-model> and the underyling @google/model-viewer has finished loading. You can use the viewer.addEventListener("loaded", ...) event to know when the property is available.

See the @google/model-viewer documentation for more information.

Related example


The fulscreen status of the viewer.

Default valueOptions
falseAny boolean value

Fullscreen mode is not fully supported on gallery mode, on mobile.


The AR status of the viewer. This property will be set to true if the AR mode is active, or if the QR code is displayed.

Default valueOptions
falseAny boolean value


The properties of the currently displayed item.

viewerItemIndexnumberThe displayed item index
viewerItemObjectThe displayed item
viewerItem.typestringType of the item
viewerItem.canBeZoomedInbooleanIf the current item allows to be zoomed in

Other properties may be available depending on the item type.


When viewing a product in AR a banner can be configured with the following options:

Related example

PropertyTypeDisplayed onExample ValueDescription
androidTitlestringAndroid"Emma Armchair, a fully upholstered chair"Sets a custom title for Android banners. Useful for displaying extra information specific to Android devices.
displayOnstring"ios-android" "ios" "android" undefinedSpecifies which platform(s) the banner should be displayed on.
iosActionstringiOS"Add to cart"Defines the text of the action button on iOS.
iosPricestringiOS"$1500"Displays the product's price on iOS banners.
iosSubtitlestringiOS"A fully upholstered chair"Sets the subtitle text for iOS banners.
iosTitlestringiOS"Emma Armchair"Specifies the main title for the banner on both iOS and Android.
redirectUrlstringiOS, Android""URL that users will be redirected to after using the banner CTA.

This property can be read and written to. It is important to note that you have to update the reference to the object for the changes to be picked up by the viewer, like:

// ⚠️ Bad, this will not work
viewer.arBanner.iosAction = "Read More";

// ✅ Good, this will work
viewer.arBanner = { ...viewer.arBanner, iosAction: "Read More" };

Additional Notes

Banners may appear differently on iOS and Android due to platform-specific constraints.

  • Both iOS and Android banners feature a button to enhance user engagement. However, their behaviors differ:
    • On iOS, the button triggers a specific event.
    • On Android, the button redirects users to a specific page and is labeled "Visit" by default.
  • Android banners support only one text field. The androidTitle property is designed to address this limitation, enabling a unique title display only for Android users.


animateToFrame(frame, options)

Animates to the given frame. Only affects the 360 viewers.

frameintThe frame
optionsSpringOptionsAnimation options

Related example


Sets the proxy to use for fetching resources. This is primarily used for debugging purposes.

proxystringThe proxy to use


Stops any zoom animation immediately and return to the active item.


Certain events are triggered by the viewer instance. You can listen for these events by using the addEventListener method on the viewer instance.

const viewer = document.querySelector("cylindo-viewer");
viewer.addEventListener("frame-change", event => {
console.log("New frame", event.detail);


Fires when any of the viewer's state has changed. This is primarily used for debugging purposes.

Detail typeDescription
StoreStateThe new state of the internal store


This event is triggered when the AR button could not be loaded. It will also be triggered when AR view was activated but AR view is not available because the device does not support it.

Detail typeDescription
StringError message


Fires when the AR button is ready. It contains the path to the 3D model.

Detail Object PropertiesDescription


Fires when the remote configuration has changed. This is triggered each time the remote configuration finishes loading, so may change once per time the remote-config attribute is changed.

Detail typeDescription
ObjectThe new configuration


This event is triggered by the viewer whenever an unexpected error occurs. This is used for logging purposes.

Detail typeDescription
ErrorThe error object

Related example


Triggered when the viewer fails to load or find any graceful fallback on its own, for example when a product cannot be found.

Detail typeDescription

Related example


Triggered when the features of the product were changed before the content was loaded.

Detail typeDescription
Record<String, String>The set of features that was canceled


Triggered when the features of the product have changed.

See our guide on creating an options configurator for more information.

Detail typeDescription
Record<String, String>The new features

Related example


This is triggered whenever the current frame changes. Only affects the 360 viewers.

Detail typeDescription
numberThe new frame


Fires when the fullscreen status changes. This is triggered when the fullscreen button is pressed, and when the fullscreen mode is exited.

Detail typeDescription
booleanThe new fullscreen status


Fires when the active item changes. This is usually the result of the user using the nav-buttons, clicking on a thumbnail or scrolling while the viewer is in gallery mode.

Detail object propertyTypeDescription
indexnumberThe new active item index
itemObjectThe new active item
item.typestringType of the item
item.canBeZoomedInbooleanIf the new active item allows to be zoomed in


Fires when the list of items changes. This is usually triggered whenever an item is added or removed from the DOM.

Detail typeDescription
Object[]The new list of items


Fires each time the viewer reaches a fully loaded state. This could be when the viewer has finished loading all 32 images for the 360 viewer, a single frame for studio or a 3D model for the model viewer.

Detail typeDescription


Fires when the viewer is defined and its API is ready to be interacted with.

viewer.addEventListener("ready", () => {
viewer.zoom = 3;


This is triggered when users stop spinning the 360 viewer.

Detail typeDescription
numberThe index of the frame after spinning


This is triggered when users start spinning the 360 viewer.

Detail typeDescription
numberIndex of the frame when starting to spin


Will trigger each frame that the zoom level has changed.

Detail typeDescription
numberThe new zoom level


Will trigger when the zoom animation has come to a stop. This is often preferable to using zoom-change as it will only trigger once instead of each requested frame during the animation.

Detail typeDescription

(deprecated) ar-mode-init

Emission of this event requests the initiation of the AR mode in the component.


ar-mode-init event is now deprecated. Please use the ar API instead.

Detail typeDescription

Related example



The aspect-ratio of the viewer, applied to browser that doesn't support the aspect-ratio css property.

Default valueOptions
4 / 3Any valid aspect-ratio value


The height of the progress bar.

Default valueOptions
5pxAny CSS size


The color of the progress bar.

Default valueOptions
#0006Any CSS color


The color of floating action button (FAB).

Default valueOptions
#617787Any CSS color


The background color of FABs.

Default valueOptions
#e7edf1Any CSS color


Outline of a disabled fab button.

Default valueOptions
nonecss outline


z-index of the fullscreen modal on iPhones.

Default valueOptions
250css z-index

The Full Screen API is not available on iPhones. Instead, we are positioning the element in the foreground. It has a z-index: 250; by default. You can use the CSS variable above to override it.


Web component libraries use the ::part pseudo-element to expose internal parts of the component for styling. This section provides an overview of the parts available for customization in this library.

To alter states like :hover, use specific sub-selectors. For a deeper understanding of the ::part pseudo-element, visit the MDN Documentation or see a related example.


There is currently a bug with ::part CSS pseudo-element on Chrome. As a workaround, the user can set some CSS variables on the disabled button elements (FABs, Arrows). If the need arises for more, please get in touch with the support team.


Instead of replacing all the Floating Action Buttons components with a custom one via slots, you can instead scope your external CSS with cylindo-viewer::part(fab) to change the look of all FABs.


This part styles the button responsible for entering and exiting the fullscreen mode.

Use this part to style the navigation button that shows the next item.

This part styles the navigation button that displays the previous item.


Modify the appearance of the button to initiate the AR mode.


Style the button that closes the QR modal with this part.

thumbnail-bar-fullscreen-container & thumbnail-bar

These two parts could be usefull if you are creating your own thumbnail bar, and you need to change the default styles for the thumbnail fullscreen container as well as its slot.


This part caters to the button's style when zooming in.


Style the button designed for zooming out using this part.


Style the area displaying the viewer's content.



The slot="placeholder" is an important concept in the viewer. It is used to show a placeholder image while the viewer is registering and loading content. This ensures the best possible time to first paint. By defining a placeholder image, you can skip defining both customer-id and code attributes on the <cylindo-viewer> component as these can be fetched from the placeholder image.

See best-practices on using a placeholder image.


Slots are not reactive, meaning that if you change the src attribute, the viewer will not update the current product. You will need to set the code attribute on the <cylindo-viewer> component to change the product reactively.

Related example


slot="thumbnail-bar" is reserved for content that is placed in the thumbnail bar part of the viewer. You can use the <cylindo-thumbnail-bar> component in the thumbnail bar.

Related example

Custom thumbnail bar

You can also use your own thumbnail bar with the viewer. You can check this basic example to get you started.