Choosing Ant Design: Modal vs Drawer – A Practical Decision Guide
Decide whether to use Ant Design’s Modal or Drawer for your next UI. Compare focus trapping, scroll behavior, dismissal, and positioning, then see a concrete form example and how to verify it.
19 Sept 2025, 03:38 UTC

Decision & Constraints
When you need a temporary UI overlay in a React application that uses Ant Design 5.x, you typically choose between Modal and Drawer. The core decision is whether the user must commit to an action before returning to the main content or whether they can keep interacting with the page while a side panel is open.
Use a Modal when:
- The interaction is critical – e.g., confirming a destructive action or submitting a form that needs full focus.
- You want to block background scrolling and prevent accidental clicks on underlying elements.
- Accessibility requires a strict focus trap and role="dialog" semantics.
Use a Drawer when:
- The panel is a contextual helper – e.g., filters, settings, or a live chat window.
- You want to allow the user to continue scrolling the main page while the panel is visible.
- The panel can be dismissed by clicking outside or pressing ESC without breaking the workflow.
Supported Options Comparison
| Feature | Modal | Drawer |
|---|---|---|
| Focus trap | Required – maskClosable={false} enforces it | Optional – maskClosable={false} or bodyStyle={{overflow:'hidden'}} |
| Background scroll | Disabled by default | Enabled by default |
| Dismiss method | Close button, ESC, outside click (if maskClosable) | Close button, ESC, outside click |
| Position | Centered | Left, Right, Top, Bottom (default Right) |
| Size control | Width/Height props | Width/Height props |
| Performance | Small DOM overhead | Slightly larger DOM due to overlay |
| Usage pattern | Critical, one‑time actions | Persistent, contextual panels |
Trade‑offs
Because Modals block interaction, they interrupt the user’s flow. This is beneficial for actions that require confirmation or data entry, but can feel intrusive if overused. The focus trap and aria-modal attribute also help screen‑reader users, making Modals more accessible out of the box.
Drawers preserve the main content’s context and allow the user to keep scrolling. However, if the drawer covers a large portion of the screen, it can obscure important information. Accessibility is less strict; developers must ensure focus order and provide clear close controls.
Performance differences are minimal for most applications, but if you open many Drawers simultaneously, the overlay can add to the DOM size.
Concrete Implementation – Form Inside a Modal
Below is a minimal React component that demonstrates a form inside a Modal. The form validates the name and email fields before allowing submission. Replace the placeholder functions with your own handlers.
import React, { useState } from 'react';
import { Modal, Form, Input, Button } from 'antd';
const UserFormModal = ({ visible, onCancel }) => {
const [form] = Form.useForm();
const onOk = () => {
form.validateFields()
.then(values => {
console.log('Submitted:', values);
form.resetFields();
onCancel();
})
.catch(info => {
console.log('Validation Failed:', info);
});
};
return (
<Modal
title="Create User"
visible={visible}
onOk={onOk}
onCancel={onCancel}
maskClosable={false}
okText="Save"
cancelText="Cancel"
>
<Form form={form} layout="vertical" name="userForm">
<Form.Item
name="name"
label="Name"
rules={[{ required: true, message: 'Please enter your name' }]}>
<Input placeholder="John Doe" />
</Form.Item>
<Form.Item
name="email"
label="Email"
rules={[
{ required: true, message: 'Please enter your email' },
{ type: 'email', message: 'Please enter a valid email' },
]}>
<Input placeholder="[contact removed]" />
</Form.Item>
</Form>
</Modal>
);
};
export default UserFormModal;
To render the modal, control the visible prop from a parent component and provide onCancel to close it. The maskClosable={false} prop ensures that clicking outside does not dismiss the modal, maintaining the focus trap.
Concrete Implementation – Equivalent Drawer
Swap the Modal component for Drawer and adjust the positioning. The code below keeps the same form but places it in a right‑hand drawer.
import { Drawer, Form, Input, Button } from 'antd';
const UserFormDrawer = ({ visible, onClose }) => {
const [form] = Form.useForm();
const onSubmit = () => {
form.validateFields()
.then(values => {
console.log('Submitted:', values);
form.resetFields();
onClose();
})
.catch(info => console.log('Validation Failed:', info));
};
return (
<Drawer
title="Create User"
placement="right"
width={400}
visible={visible}
onClose={onClose}
destroyOnClose
>
<Form form={form} layout="vertical" name="userFormDrawer">
<Form.Item name="name" label="Name" rules={[{ required: true }]}>
<Input placeholder="John Doe" />
</Form.Item>
<Form.Item name="email" label="Email" rules={[{ type: 'email' }]}>
<Input placeholder="[contact removed]" />
</Form.Item>
<Form.Item>
<Button type="primary" onClick={onSubmit}>Save</Button>
</Form.Item>
</Form>
</Drawer>
);
};
export default UserFormDrawer;
Verification Checklist
- Render the component in a React application with Ant Design 5.x loaded.
- Open the modal/drawer and confirm:
- Modal: the background cannot be scrolled; focus stays inside the modal; pressing ESC or clicking the close button dismisses it.
- Drawer: the main page remains scrollable; the drawer can be closed via ESC or clicking outside.
- Use a screen reader to ensure the modal announces a dialog and traps focus. Inspect the overlay element – it should have
role="dialog"andaria-modal="true". - Check the form validation by attempting to submit empty fields; error messages should appear.
- Open the browser console for any Ant Design warnings about missing
aria-labelledbyoraria-describedbyattributes. Add them if necessary. - Verify that the drawer’s width is stable by providing a
widthprop; without it the drawer may shift content.
Limitations & Practical Tips
- Both components rely on Ant Design’s CSS. If you use a custom
ConfigProvider, ensure the theme is applied correctly. - The
maskClosableprop is the only way to prevent a modal from closing when clicking the mask; otherwise focus might escape. - Drawers do not trap focus by default. If strict accessibility is required, set
focusTriggerAfterClose={false}and manage focus manually. - Large drawers can cause layout shifts; always set an explicit
widthorheightto keep the layout stable. - When using
destroyOnCloseon a drawer, the form state resets on each open. If you need to preserve state, remove that prop.
By following this guide, you can choose the component that best matches your user interaction pattern and verify that it behaves as expected.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.