DevExtreme v24.1 is now available.

Explore our newest features/capabilities and share your thoughts with us.

Your search did not match any results.

Scrolling

This demo shows two implementations of scrolling in the Popup component.

When you click the first Show Popup button, a Popup with a native scrollbar appears. The component always displays a native scrollbar when the height of the Popup's content is greater than that of the Popup.

Backend API
import React, { useCallback, useMemo, useState } from 'react'; import { Button } from 'devextreme-react'; import { Popup, ToolbarItem } from 'devextreme-react/popup'; import ScrollView from 'devextreme-react/scroll-view'; export default function App() { const [popupVisible, setPopupVisible] = useState(false); const [popupWithScrollViewVisible, setPopupWithScrollViewVisible] = useState(false); const showPopup = useCallback(() => { setPopupVisible(true); }, [setPopupVisible]); const showPopupWithScrollView = useCallback(() => { setPopupWithScrollViewVisible(true); }, [setPopupWithScrollViewVisible]); const hide = useCallback(() => { setPopupVisible(false); setPopupWithScrollViewVisible(false); }, [setPopupVisible, setPopupWithScrollViewVisible]); const bookButtonOptions = useMemo(() => ({ width: 300, text: 'Book', type: 'default', stylingMode: 'contained', onClick: hide, }), [hide]); return ( <React.Fragment> <div className="demo-container"> <div className="button-container"> <Button text="Show Popup" type="default" width={300} onClick={showPopup} /> <div className="label"> A native scrollable container </div> </div> <div className="button-container"> <Button text="Show Popup" width={300} onClick={showPopupWithScrollView} /> <div className="label"> The ScrollView </div> </div> </div> <Popup width={360} height={320} visible={popupVisible} onHiding={hide} hideOnOutsideClick={true} showCloseButton={true} title="Downtown Inn"> <div className="popup-content"> <div className="caption">Description</div> In the heart of LA&apos;s business district, the Downtown Inn has a welcoming staff and award winning restaurants that remain open 24 hours a day. Use our conference room facilities to conduct meetings and have a drink at our beautiful rooftop bar. <br /><br /> <div className="content"> <div> <div className="caption">Features</div> <div>Concierge</div> <div>Restaurant</div> <div>Valet Parking</div> <div>Fitness Center</div> <div>Sauna</div> <div>Airport Shuttle</div> </div> <div> <div className="caption">Rooms</div> <div>Climate control</div> <div>Air conditioning</div> <div>Coffee/tea maker</div> <div>Iron/ironing</div> </div> </div> </div> <ToolbarItem widget="dxButton" toolbar="bottom" location="center" options={bookButtonOptions} /> </Popup> <Popup width={360} height={320} visible={popupWithScrollViewVisible} onHiding={hide} hideOnOutsideClick={true} showCloseButton={true} title="Downtown Inn"> <ScrollView width='100%' height='100%'> <div className="caption">Description</div> In the heart of LA&apos;s business district, the Downtown Inn has a welcoming staff and award winning restaurants that remain open 24 hours a day. Use our conference room facilities to conduct meetings and have a drink at our beautiful rooftop bar. <br /><br /> <div className="content"> <div> <div className="caption">Features</div> <div>Concierge</div> <div>Restaurant</div> <div>Valet Parking</div> <div>Fitness Center</div> <div>Sauna</div> <div>Airport Shuttle</div> </div> <div> <div className="caption">Rooms</div> <div>Climate control</div> <div>Air conditioning</div> <div>Coffee/tea maker</div> <div>Iron/ironing</div> </div> </div> </ScrollView> <ToolbarItem widget="dxButton" toolbar="bottom" location="center" options={bookButtonOptions} /> </Popup> </React.Fragment> ); }
import React, { useCallback, useMemo, useState } from 'react'; import { Button } from 'devextreme-react'; import { Popup, ToolbarItem } from 'devextreme-react/popup'; import ScrollView from 'devextreme-react/scroll-view'; export default function App() { const [popupVisible, setPopupVisible] = useState(false); const [popupWithScrollViewVisible, setPopupWithScrollViewVisible] = useState(false); const showPopup = useCallback(() => { setPopupVisible(true); }, [setPopupVisible]); const showPopupWithScrollView = useCallback(() => { setPopupWithScrollViewVisible(true); }, [setPopupWithScrollViewVisible]); const hide = useCallback(() => { setPopupVisible(false); setPopupWithScrollViewVisible(false); }, [setPopupVisible, setPopupWithScrollViewVisible]); const bookButtonOptions = useMemo( () => ({ width: 300, text: 'Book', type: 'default', stylingMode: 'contained', onClick: hide, }), [hide], ); return ( <React.Fragment> <div className="demo-container"> <div className="button-container"> <Button text="Show Popup" type="default" width={300} onClick={showPopup} /> <div className="label"> A native scrollable container </div> </div> <div className="button-container"> <Button text="Show Popup" width={300} onClick={showPopupWithScrollView} /> <div className="label"> The ScrollView </div> </div> </div> <Popup width={360} height={320} visible={popupVisible} onHiding={hide} hideOnOutsideClick={true} showCloseButton={true} title="Downtown Inn" > <div className="popup-content"> <div className="caption">Description</div> In the heart of LA&apos;s business district, the Downtown Inn has a welcoming staff and award winning restaurants that remain open 24 hours a day. Use our conference room facilities to conduct meetings and have a drink at our beautiful rooftop bar. <br /> <br /> <div className="content"> <div> <div className="caption">Features</div> <div>Concierge</div> <div>Restaurant</div> <div>Valet Parking</div> <div>Fitness Center</div> <div>Sauna</div> <div>Airport Shuttle</div> </div> <div> <div className="caption">Rooms</div> <div>Climate control</div> <div>Air conditioning</div> <div>Coffee/tea maker</div> <div>Iron/ironing</div> </div> </div> </div> <ToolbarItem widget="dxButton" toolbar="bottom" location="center" options={bookButtonOptions} /> </Popup> <Popup width={360} height={320} visible={popupWithScrollViewVisible} onHiding={hide} hideOnOutsideClick={true} showCloseButton={true} title="Downtown Inn" > <ScrollView width="100%" height="100%" > <div className="caption">Description</div> In the heart of LA&apos;s business district, the Downtown Inn has a welcoming staff and award winning restaurants that remain open 24 hours a day. Use our conference room facilities to conduct meetings and have a drink at our beautiful rooftop bar. <br /> <br /> <div className="content"> <div> <div className="caption">Features</div> <div>Concierge</div> <div>Restaurant</div> <div>Valet Parking</div> <div>Fitness Center</div> <div>Sauna</div> <div>Airport Shuttle</div> </div> <div> <div className="caption">Rooms</div> <div>Climate control</div> <div>Air conditioning</div> <div>Coffee/tea maker</div> <div>Iron/ironing</div> </div> </div> </ScrollView> <ToolbarItem widget="dxButton" toolbar="bottom" location="center" options={bookButtonOptions} /> </Popup> </React.Fragment> ); }
import React from 'react'; import ReactDOM from 'react-dom'; import App from './App.tsx'; ReactDOM.render( <App />, document.getElementById('app'), );
window.exports = window.exports || {}; window.config = { transpiler: 'ts', typescriptOptions: { module: 'system', emitDecoratorMetadata: true, experimentalDecorators: true, jsx: 'react', }, meta: { 'react': { 'esModule': true, }, 'typescript': { 'exports': 'ts', }, 'devextreme/time_zone_utils.js': { 'esModule': true, }, 'devextreme/localization.js': { 'esModule': true, }, 'devextreme/viz/palette.js': { 'esModule': true, }, }, paths: { 'npm:': 'https://unpkg.com/', }, defaultExtension: 'js', map: { 'ts': 'npm:plugin-typescript@4.2.4/lib/plugin.js', 'typescript': 'npm:typescript@4.2.4/lib/typescript.js', 'react': 'npm:react@17.0.2/umd/react.development.js', 'react-dom': 'npm:react-dom@17.0.2/umd/react-dom.development.js', 'prop-types': 'npm:prop-types@15.8.1/prop-types.js', 'rrule': 'npm:rrule@2.6.4/dist/es5/rrule.js', 'luxon': 'npm:luxon@1.28.1/build/global/luxon.min.js', 'es6-object-assign': 'npm:es6-object-assign@1.1.0', 'devextreme': 'npm:devextreme@24.1.4/cjs', 'devextreme-react': 'npm:devextreme-react@24.1.4/cjs', 'jszip': 'npm:jszip@3.10.1/dist/jszip.min.js', 'devextreme-quill': 'npm:devextreme-quill@1.7.1/dist/dx-quill.min.js', 'devexpress-diagram': 'npm:devexpress-diagram@2.2.10/dist/dx-diagram.js', 'devexpress-gantt': 'npm:devexpress-gantt@4.1.56/dist/dx-gantt.js', '@devextreme/runtime': 'npm:@devextreme/runtime@3.0.13', 'inferno': 'npm:inferno@7.4.11/dist/inferno.min.js', 'inferno-compat': 'npm:inferno-compat/dist/inferno-compat.min.js', 'inferno-create-element': 'npm:inferno-create-element@7.4.11/dist/inferno-create-element.min.js', 'inferno-dom': 'npm:inferno-dom/dist/inferno-dom.min.js', 'inferno-hydrate': 'npm:inferno-hydrate@7.4.11/dist/inferno-hydrate.min.js', 'inferno-clone-vnode': 'npm:inferno-clone-vnode/dist/inferno-clone-vnode.min.js', 'inferno-create-class': 'npm:inferno-create-class/dist/inferno-create-class.min.js', 'inferno-extras': 'npm:inferno-extras/dist/inferno-extras.min.js', 'devextreme-cldr-data': 'npm:devextreme-cldr-data@1.0.3', // SystemJS plugins 'plugin-babel': 'npm:systemjs-plugin-babel@0.0.25/plugin-babel.js', 'systemjs-babel-build': 'npm:systemjs-plugin-babel@0.0.25/systemjs-babel-browser.js', // Prettier 'prettier/standalone': 'npm:prettier@2.8.8/standalone.js', 'prettier/parser-html': 'npm:prettier@2.8.8/parser-html.js', }, packages: { 'devextreme': { defaultExtension: 'js', }, 'devextreme-react': { main: 'index.js', }, 'devextreme/events/utils': { main: 'index', }, 'devextreme/localization/messages': { format: 'json', defaultExtension: 'json', }, 'devextreme/events': { main: 'index', }, 'es6-object-assign': { main: './index.js', defaultExtension: 'js', }, }, packageConfigPaths: [ 'npm:@devextreme/*/package.json', 'npm:@devextreme/runtime@3.0.13/inferno/package.json', ], babelOptions: { sourceMaps: false, stage0: true, react: true, }, }; System.config(window.config);
import React from 'react'; import ReactDOM from 'react-dom'; import App from './App.js'; ReactDOM.render(<App />, document.getElementById('app'));
<!DOCTYPE html> <html lang="en"> <head> <title>DevExtreme Demo</title> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=5.0" /> <link rel="stylesheet" type="text/css" href="https://cdn3.devexpress.com/jslib/24.1.4/css/dx.light.css" /> <link rel="stylesheet" type="text/css" href="styles.css" /> <script src="https://unpkg.com/core-js@2.6.12/client/shim.min.js"></script> <script src="https://unpkg.com/systemjs@0.21.3/dist/system.js"></script> <script type="text/javascript" src="config.js"></script> <script type="text/javascript"> System.import("./index.tsx"); </script> </head> <body class="dx-viewport"> <div class="demo-container"> <div id="app"></div> </div> </body> </html>
.label { font-size: 12px; } .demo-container { height: 450px; display: flex; align-items: center; flex-direction: column; justify-content: center; gap: 40px; } .button-container { display: flex; align-items: center; flex-direction: column; justify-content: center; gap: 15px; } .dx-popup-content { font-size: 12px; } .caption { padding-bottom: 8px; font-weight: 500; } .content { display: flex; justify-content: space-between; } .popup-content { height: 100%; width: 100%; }

A click on the second Show Popup button also displays a Popup with a scrollbar, but this scrollbar belongs to the ScrollView component. This implementation is more flexible. For example, you can enable right-to-left representation or scroll the content to a specific position. For more information about the available options, refer to the ScrollView API section.

To implement the second solution, follow the steps below:

  1. Wrap the content in the ScrollView component and place it in the Popup container.

  2. Set the height and width of the ScrollView to 100% of the popup content area.