Custom CSS Guide
This guide explains how to use the Custom CSS feature in NotionApps to style a published app for client-facing or brand-specific use cases.
Custom CSS gives app builders a controlled way to customize the visual appearance of the end-user app. You can use it to adjust fonts, text colors, buttons, form fields, links, images, spacing, and responsive behavior without changing the app’s data structure or backend logic.
Who This Guide Is For
Section titled “Who This Guide Is For”This guide is intended for:
- App builders who want to apply brand styling to a NotionApps app.
- Technical writers documenting NotionApps customization workflows.
- Customer success teams helping users style client-facing apps.
- Developers or advanced users who understand basic CSS selectors.
What You Can Customize
Section titled “What You Can Customize”With Custom CSS, you can style many visible parts of the end-user app, including:
- Text color and typography
- Headings, labels, body text, and links
- Buttons and button hover states
- Inputs, textareas, dropdowns, and placeholders
- Images and icons
- Lists and repeated records
- Borders, spacing, backgrounds, and shadows
- Mobile-specific layouts using media queries
Custom CSS is best suited for visual customization. It should not be used to control access, hide sensitive data, replace validation logic, or change application behavior.
Before You Begin
Section titled “Before You Begin”Before writing Custom CSS, make sure:
- You have access to the app in the NotionApps builder.
- The app has been created and can be saved.
- You know the styling goal, such as applying a brand font, changing button colors, or styling form fields.
- You understand that users must save and re-publish the app before published users see the latest CSS.
Add Custom CSS in the Builder
Section titled “Add Custom CSS in the Builder”To add Custom CSS:
- Open the app in the NotionApps builder.
- Go to the app settings area.
- Find the Custom CSS section.
- Enable Custom CSS.
- Paste your CSS into the Custom CSS editor.

- Save the app.
- Publish or re-publish the app.
- Open the published app and verify the style changes.
Understand the End-User Root Selector
Section titled “Understand the End-User Root Selector”The NotionApps end-user app is wrapped in a root element with this attribute:
data-notionapps-end-user-root="true"When writing Custom CSS, scope your selectors to that root element:
[data-notionapps-end-user-root="true"] { color: #111827;}This is the recommended pattern because it limits your CSS to the NotionApps end-user app.
Why Scoping Matters
Section titled “Why Scoping Matters”Scoped CSS is safer than global CSS.
For example, this selector targets every button inside the NotionApps end-user app:
[data-notionapps-end-user-root="true"] button { border-radius: 6px;}This selector targets every button on the page:
button { border-radius: 6px;}The second example is broader and can affect elements outside the app. Use scoped selectors whenever possible.
Create Reusable Brand Variables
Section titled “Create Reusable Brand Variables”CSS variables make brand styles easier to maintain. Define them once on the root selector:
[data-notionapps-end-user-root="true"] { --brand-primary: #0f766e; --brand-primary-dark: #115e59; --brand-border: #d8ebe7; --brand-text: #111827; --brand-muted-text: #64748b;
color: var(--brand-text); font-family: "Poppins", sans-serif;}You can then reuse those values:
[data-notionapps-end-user-root="true"] button { background: var(--brand-primary);}Style All Text
Section titled “Style All Text”To change the color of all text inside the end-user app, target both the root and all child elements:
[data-notionapps-end-user-root="true"],[data-notionapps-end-user-root="true"] * { color: red !important;}The universal selector * targets every descendant element.
Use this approach when you want a global text color or when testing that Custom CSS is working.
Style Form Field Text
Section titled “Style Form Field Text”Some browsers apply special rendering to form controls. If the text inside inputs, dropdowns, or textareas does not change color, add -webkit-text-fill-color.
[data-notionapps-end-user-root="true"] input,[data-notionapps-end-user-root="true"] textarea,[data-notionapps-end-user-root="true"] select { color: red !important; -webkit-text-fill-color: red !important;}Style Placeholder Text
Section titled “Style Placeholder Text”Placeholder text requires a separate selector:
[data-notionapps-end-user-root="true"] input::placeholder,[data-notionapps-end-user-root="true"] textarea::placeholder { color: #94a3b8; opacity: 1;}Use opacity: 1 because some browsers reduce placeholder opacity by default.
Style Headings
Section titled “Style Headings”Use heading selectors to style screen titles, section titles, or large text elements.
[data-notionapps-end-user-root="true"] h1,[data-notionapps-end-user-root="true"] h2,[data-notionapps-end-user-root="true"] h3 { color: #0f172a; font-weight: 700; letter-spacing: 0;}You can style heading levels separately:
[data-notionapps-end-user-root="true"] h1 { font-size: 32px;}
[data-notionapps-end-user-root="true"] h2 { font-size: 24px;}
[data-notionapps-end-user-root="true"] h3 { font-size: 18px;}Style Paragraphs, Labels, and Inline Text
Section titled “Style Paragraphs, Labels, and Inline Text”Use these selectors for common text elements:
[data-notionapps-end-user-root="true"] p,[data-notionapps-end-user-root="true"] span,[data-notionapps-end-user-root="true"] label { color: #334155;}If a label does not change, inspect the element in browser DevTools. It may be rendered as a div, span, or another element.
Style Links
Section titled “Style Links”Use the a selector for links:
[data-notionapps-end-user-root="true"] a { color: var(--brand-primary); font-weight: 500; text-decoration: underline;}
[data-notionapps-end-user-root="true"] a:hover { color: var(--brand-primary-dark);}Style Buttons
Section titled “Style Buttons”Buttons may be rendered as actual button elements or as elements with role="button". Target both:
[data-notionapps-end-user-root="true"] button,[data-notionapps-end-user-root="true"] [role="button"] { background: var(--brand-primary) !important; border-color: var(--brand-primary) !important; border-radius: 6px; color: #ffffff !important; font-weight: 600;}Add a hover state:
[data-notionapps-end-user-root="true"] button:hover,[data-notionapps-end-user-root="true"] [role="button"]:hover { background: var(--brand-primary-dark) !important; border-color: var(--brand-primary-dark) !important;}Add a disabled state:
[data-notionapps-end-user-root="true"] button:disabled { background: #cbd5e1 !important; border-color: #cbd5e1 !important; color: #64748b !important; cursor: not-allowed;}Style Inputs, Textareas, and Dropdowns
Section titled “Style Inputs, Textareas, and Dropdowns”Use these selectors for common form fields:
[data-notionapps-end-user-root="true"] input,[data-notionapps-end-user-root="true"] textarea,[data-notionapps-end-user-root="true"] select { background: #ffffff; border: 1px solid var(--brand-border) !important; border-radius: 6px; color: #111827; font-family: "Poppins", sans-serif;}Add focus styling:
[data-notionapps-end-user-root="true"] input:focus,[data-notionapps-end-user-root="true"] textarea:focus,[data-notionapps-end-user-root="true"] select:focus { border-color: var(--brand-primary) !important; box-shadow: 0 0 0 3px rgba(15, 118, 110, 0.18); outline: none;}Style Lists
Section titled “Style Lists”Use list selectors for unordered and ordered lists:
[data-notionapps-end-user-root="true"] ul,[data-notionapps-end-user-root="true"] ol { padding-left: 20px;}
[data-notionapps-end-user-root="true"] li { margin-bottom: 8px;}Style Images
Section titled “Style Images”Use image selectors for rounded corners or consistent sizing:
[data-notionapps-end-user-root="true"] img { border-radius: 6px; max-width: 100%;}If images are cropped or displayed in cards, test the change on multiple screen sizes.
Style Icons and SVGs
Section titled “Style Icons and SVGs”Icons are often rendered as SVGs. You can target SVG elements:
[data-notionapps-end-user-root="true"] svg { color: var(--brand-primary);}Some SVGs use path elements:
[data-notionapps-end-user-root="true"] svg path { stroke: currentColor;}Use currentColor when possible so icons inherit the surrounding text color.
Style Containers and Cards
Section titled “Style Containers and Cards”Many app layouts are built with div elements. You can target them, but use broad div selectors carefully.
[data-notionapps-end-user-root="true"] div { border-color: #e5e7eb;}This rule applies to every div inside the app. For layout styling, inspect the element first and look for a more specific selector when possible.
Use Attribute Selectors
Section titled “Use Attribute Selectors”Attribute selectors target elements by attributes.
The root selector is an attribute selector:
[data-notionapps-end-user-root="true"] { color: #111827;}Button-like elements can be targeted by role:
[data-notionapps-end-user-root="true"] [role="button"] { cursor: pointer;}You can also target input types:
[data-notionapps-end-user-root="true"] input[type="text"],[data-notionapps-end-user-root="true"] input[type="email"],[data-notionapps-end-user-root="true"] input[type="number"] { border-radius: 6px;}Use Pseudo-Classes
Section titled “Use Pseudo-Classes”Pseudo-classes target states such as hover, focus, disabled, or checked.
[data-notionapps-end-user-root="true"] button:hover { background: var(--brand-primary-dark) !important;}
[data-notionapps-end-user-root="true"] input:focus { outline: 2px solid var(--brand-primary);}
[data-notionapps-end-user-root="true"] button:disabled { opacity: 0.6;}Use Pseudo-Elements
Section titled “Use Pseudo-Elements”Pseudo-elements target parts of an element, such as placeholders.
[data-notionapps-end-user-root="true"] input::placeholder { color: #94a3b8;}Use Media Queries
Section titled “Use Media Queries”Media queries let you apply styles only at certain viewport widths.
Example for mobile:
@media (max-width: 600px) { [data-notionapps-end-user-root="true"] button { min-height: 44px; width: 100%; }
[data-notionapps-end-user-root="true"] h1 { font-size: 24px; }}Example for larger screens:
@media (min-width: 900px) { [data-notionapps-end-user-root="true"] { font-size: 16px; }}Use Custom Fonts
Section titled “Use Custom Fonts”If the app also uses the Custom Font feature, set the same font family in Custom CSS:
[data-notionapps-end-user-root="true"],[data-notionapps-end-user-root="true"] * { font-family: "Poppins", sans-serif;}If a font is loaded from Google Fonts, make sure the font family name in CSS matches the font name exactly.
Example:
Font family: PoppinsStylesheet URL: https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;600;700&display=swapCSS:
[data-notionapps-end-user-root="true"] { font-family: "Poppins", sans-serif;}Example: Make All Font Color Red
Section titled “Example: Make All Font Color Red”Use this example to verify that Custom CSS is working:
[data-notionapps-end-user-root="true"],[data-notionapps-end-user-root="true"] * { color: red !important;}
[data-notionapps-end-user-root="true"] input,[data-notionapps-end-user-root="true"] textarea,[data-notionapps-end-user-root="true"] select,[data-notionapps-end-user-root="true"] button { color: red !important; -webkit-text-fill-color: red !important;}
[data-notionapps-end-user-root="true"] input::placeholder,[data-notionapps-end-user-root="true"] textarea::placeholder { color: red !important; opacity: 1;}After saving and publishing, all visible text inside the end-user app should appear red.
Example: Branded Buttons and Fields
Section titled “Example: Branded Buttons and Fields”This example applies a client brand color to buttons and form controls:
[data-notionapps-end-user-root="true"] { --brand-primary: #0f766e; --brand-primary-dark: #115e59; --brand-border: #d8ebe7; --brand-text: #111827;
color: var(--brand-text); font-family: "Poppins", sans-serif;}
[data-notionapps-end-user-root="true"] button,[data-notionapps-end-user-root="true"] [role="button"] { background: var(--brand-primary) !important; border-color: var(--brand-primary) !important; border-radius: 6px; color: #ffffff !important; font-weight: 600;}
[data-notionapps-end-user-root="true"] button:hover,[data-notionapps-end-user-root="true"] [role="button"]:hover { background: var(--brand-primary-dark) !important; border-color: var(--brand-primary-dark) !important;}
[data-notionapps-end-user-root="true"] input,[data-notionapps-end-user-root="true"] textarea,[data-notionapps-end-user-root="true"] select { border-color: var(--brand-border) !important; border-radius: 6px; font-family: "Poppins", sans-serif;}Example: Softer Form Styling
Section titled “Example: Softer Form Styling”This example makes form fields feel lighter and more spacious:
[data-notionapps-end-user-root="true"] input,[data-notionapps-end-user-root="true"] textarea,[data-notionapps-end-user-root="true"] select { background: #f8fafc; border: 1px solid #cbd5e1 !important; border-radius: 6px; padding: 10px 12px;}
[data-notionapps-end-user-root="true"] input:focus,[data-notionapps-end-user-root="true"] textarea:focus,[data-notionapps-end-user-root="true"] select:focus { background: #ffffff; border-color: #0f766e !important; box-shadow: 0 0 0 3px rgba(15, 118, 110, 0.16);}Example: Mobile-Friendly Buttons
Section titled “Example: Mobile-Friendly Buttons”This example makes buttons easier to tap on mobile screens:
@media (max-width: 600px) { [data-notionapps-end-user-root="true"] button, [data-notionapps-end-user-root="true"] [role="button"] { min-height: 44px; width: 100%; }}Verify That Custom CSS Worked
Section titled “Verify That Custom CSS Worked”After saving and publishing, open the end-user app and inspect it with browser DevTools.
Check for the root element:
data-notionapps-end-user-root="true"Check for the custom style tag:
<style id="notionapps-end-user-customization">If that style tag appears, the published app received the Custom CSS payload.
Troubleshooting
Section titled “Troubleshooting”CSS Does Not Appear
Section titled “CSS Does Not Appear”Confirm the following:
- Custom CSS is enabled.
- The app was saved after editing the CSS.
- The app was re-published.
- The published app was hard-refreshed.
- The page contains
id="notionapps-end-user-customization".
CSS Appears but Does Not Apply
Section titled “CSS Appears but Does Not Apply”The existing component style may be more specific than your selector. Increase specificity:
[data-notionapps-end-user-root="true"] button { background: #0f766e !important;}Use !important only when needed.
Input Text Does Not Change Color
Section titled “Input Text Does Not Change Color”Add -webkit-text-fill-color:
[data-notionapps-end-user-root="true"] input { color: red !important; -webkit-text-fill-color: red !important;}Placeholder Text Does Not Change
Section titled “Placeholder Text Does Not Change”Target placeholders separately:
[data-notionapps-end-user-root="true"] input::placeholder { color: red !important; opacity: 1;}Styles Look Different on Mobile
Section titled “Styles Look Different on Mobile”Add mobile-specific media queries:
@media (max-width: 600px) { [data-notionapps-end-user-root="true"] { font-size: 15px; }}A Broad Selector Changed Too Much
Section titled “A Broad Selector Changed Too Much”If a rule affects more than expected, make it narrower.
Broad:
[data-notionapps-end-user-root="true"] div { padding: 12px;}Narrower:
[data-notionapps-end-user-root="true"] form div { padding: 12px;}Recommended Authoring Workflow
Section titled “Recommended Authoring Workflow”- Define the brand variables first.
- Add typography styles.
- Style buttons.
- Style form fields.
- Add hover, focus, and disabled states.
- Add mobile media queries.
- Save and publish.
- Verify in the published end-user app.
- Inspect problem elements with DevTools.
- Refine selectors if a rule is too broad.
CSS Selector Reference
Section titled “CSS Selector Reference”| Goal | Selector |
|---|---|
| App root | [data-notionapps-end-user-root="true"] |
| All elements in app | [data-notionapps-end-user-root="true"] * |
| Headings | [data-notionapps-end-user-root="true"] h1, h2, h3 |
| Paragraphs | [data-notionapps-end-user-root="true"] p |
| Labels | [data-notionapps-end-user-root="true"] label |
| Links | [data-notionapps-end-user-root="true"] a |
| Buttons | [data-notionapps-end-user-root="true"] button |
| Button-like elements | [data-notionapps-end-user-root="true"] [role="button"] |
| Inputs | [data-notionapps-end-user-root="true"] input |
| Textareas | [data-notionapps-end-user-root="true"] textarea |
| Dropdowns | [data-notionapps-end-user-root="true"] select |
| Placeholders | [data-notionapps-end-user-root="true"] input::placeholder |
| Images | [data-notionapps-end-user-root="true"] img |
| SVG icons | [data-notionapps-end-user-root="true"] svg |
Best Practices
Section titled “Best Practices”- Scope Custom CSS to
[data-notionapps-end-user-root="true"]. - Use CSS variables for repeated brand values.
- Target both
buttonand[role="button"]. - Target placeholders separately.
- Use focus states for form accessibility.
- Use
!importantonly when needed to override existing component styles. - Avoid broad layout changes on every
div. - Test on both desktop and mobile.
- Save and re-publish after every meaningful change.
Summary
Section titled “Summary”Custom CSS in NotionApps is a flexible way to make published apps feel more polished and on-brand. The key is to write scoped, intentional CSS that targets the end-user app root. Start with broad proof-of-concept styles when testing, then refine the selectors for production-ready styling.
Builder options at a glance
Section titled “Builder options at a glance”This guide teaches a focused maker workflow. For the full screen option inventory (What it does / How to use / Why) and annotated builder screenshots, use the matching Types of Screens guide:
- Data screens: List (View Items), Details, Form (Add Item), Form (Update One Item), List (Update Items), Content
- Everyday chrome / Queue & activity: see the Types of Screens index
- Automation native screens: Native Automation Screens
Recommended defaults
Section titled “Recommended defaults”- Change one option family at a time, then publish and test on phone and desktop.
- Prefer screen-level settings in Content / Behaviour / Appearance before custom CSS/JS.
- Keep public access and navigation visibility intentional on every screen you link from this guide.