> For the complete documentation index, see [llms.txt](https://docs.notionapps.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.notionapps.com/guides/custom-css-guide.md).

# Custom CSS Guide

{% hint style="warning" %}
**Subscription requirement**

This feature requires a Premium or Enterprise NotionApps Subscription. Users on other subscriptions may not see this option in the builder.
{% endhint %}

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.

{% hint style="info" %}
Custom CSS applies to the **published end-user app**, not to the NotionApps builder interface.
{% endhint %}

## 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

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

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.

{% hint style="warning" %}
Avoid using Custom CSS to hide information that should not be visible to end users. If data should not be visible, configure permissions, screens, fields, or filters instead.
{% endhint %}

## Add Custom CSS in the Builder

To add Custom CSS:

1. Open the app in the NotionApps builder.
2. Go to the app settings area.
3. Find the **Custom CSS** section.
4. Enable Custom CSS.
5. Paste your CSS into the Custom CSS editor.

<figure><img src="/files/LSueV1VeoTJvJMm7Y7VY" alt=""><figcaption></figcaption></figure>

6. Save the app.
7. Publish or re-publish the app.
8. Open the published app and verify the style changes.

## Understand the End-User Root Selector

The NotionApps end-user app is wrapped in a root element with this attribute:

```html
data-notionapps-end-user-root="true"
```

When writing Custom CSS, scope your selectors to that root element:

```css
[data-notionapps-end-user-root="true"] {
  color: #111827;
}
```

This is the recommended pattern because it limits your CSS to the NotionApps end-user app.

{% hint style="success" %}
Best practice: Start most selectors with `[data-notionapps-end-user-root="true"]`.
{% endhint %}

## Why Scoping Matters

Scoped CSS is safer than global CSS.

For example, this selector targets every button inside the NotionApps end-user app:

```css
[data-notionapps-end-user-root="true"] button {
  border-radius: 6px;
}
```

This selector targets every button on the page:

```css
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

CSS variables make brand styles easier to maintain. Define them once on the root selector:

```css
[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:

```css
[data-notionapps-end-user-root="true"] button {
  background: var(--brand-primary);
}
```

## Style All Text

To change the color of all text inside the end-user app, target both the root and all child elements:

```css
[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.

{% hint style="warning" %}
The universal selector is powerful. Use it carefully because it affects every element inside the app.
{% endhint %}

## 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`.

```css
[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

Placeholder text requires a separate selector:

```css
[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

Use heading selectors to style screen titles, section titles, or large text elements.

```css
[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:

```css
[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

Use these selectors for common text elements:

```css
[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

Use the `a` selector for links:

```css
[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

Buttons may be rendered as actual `button` elements or as elements with `role="button"`. Target both:

```css
[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:

```css
[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:

```css
[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

Use these selectors for common form fields:

```css
[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:

```css
[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

Use list selectors for unordered and ordered lists:

```css
[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

Use image selectors for rounded corners or consistent sizing:

```css
[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

Icons are often rendered as SVGs. You can target SVG elements:

```css
[data-notionapps-end-user-root="true"] svg {
  color: var(--brand-primary);
}
```

Some SVGs use `path` elements:

```css
[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

Many app layouts are built with `div` elements. You can target them, but use broad `div` selectors carefully.

```css
[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.

{% hint style="warning" %}
Avoid adding large layout changes to all `div` elements. Broad `div` rules can unintentionally affect navigation, records, forms, and nested components.
{% endhint %}

## Use Attribute Selectors

Attribute selectors target elements by attributes.

The root selector is an attribute selector:

```css
[data-notionapps-end-user-root="true"] {
  color: #111827;
}
```

Button-like elements can be targeted by role:

```css
[data-notionapps-end-user-root="true"] [role="button"] {
  cursor: pointer;
}
```

You can also target input types:

```css
[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

Pseudo-classes target states such as hover, focus, disabled, or checked.

```css
[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

Pseudo-elements target parts of an element, such as placeholders.

```css
[data-notionapps-end-user-root="true"] input::placeholder {
  color: #94a3b8;
}
```

## Use Media Queries

Media queries let you apply styles only at certain viewport widths.

Example for mobile:

```css
@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:

```css
@media (min-width: 900px) {
  [data-notionapps-end-user-root="true"] {
    font-size: 16px;
  }
}
```

## Use Custom Fonts

If the app also uses the Custom Font feature, set the same font family in Custom CSS:

```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: Poppins
Stylesheet URL: https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;600;700&display=swap
```

CSS:

```css
[data-notionapps-end-user-root="true"] {
  font-family: "Poppins", sans-serif;
}
```

## Example: Make All Font Color Red

Use this example to verify that Custom CSS is working:

```css
[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

This example applies a client brand color to buttons and form controls:

```css
[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

This example makes form fields feel lighter and more spacious:

```css
[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

This example makes buttons easier to tap on mobile screens:

```css
@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

After saving and publishing, open the end-user app and inspect it with browser DevTools.

Check for the root element:

```html
data-notionapps-end-user-root="true"
```

Check for the custom style tag:

```html
<style id="notionapps-end-user-customization">
```

If that style tag appears, the published app received the Custom CSS payload.

## Troubleshooting

### 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

The existing component style may be more specific than your selector. Increase specificity:

```css
[data-notionapps-end-user-root="true"] button {
  background: #0f766e !important;
}
```

Use `!important` only when needed.

### Input Text Does Not Change Color

Add `-webkit-text-fill-color`:

```css
[data-notionapps-end-user-root="true"] input {
  color: red !important;
  -webkit-text-fill-color: red !important;
}
```

### Placeholder Text Does Not Change

Target placeholders separately:

```css
[data-notionapps-end-user-root="true"] input::placeholder {
  color: red !important;
  opacity: 1;
}
```

### Styles Look Different on Mobile

Add mobile-specific media queries:

```css
@media (max-width: 600px) {
  [data-notionapps-end-user-root="true"] {
    font-size: 15px;
  }
}
```

### A Broad Selector Changed Too Much

If a rule affects more than expected, make it narrower.

Broad:

```css
[data-notionapps-end-user-root="true"] div {
  padding: 12px;
}
```

Narrower:

```css
[data-notionapps-end-user-root="true"] form div {
  padding: 12px;
}
```

## Recommended Authoring Workflow

1. Define the brand variables first.
2. Add typography styles.
3. Style buttons.
4. Style form fields.
5. Add hover, focus, and disabled states.
6. Add mobile media queries.
7. Save and publish.
8. Verify in the published end-user app.
9. Inspect problem elements with DevTools.
10. Refine selectors if a rule is too broad.

## 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

* Scope Custom CSS to `[data-notionapps-end-user-root="true"]`.
* Use CSS variables for repeated brand values.
* Target both `button` and `[role="button"]`.
* Target placeholders separately.
* Use focus states for form accessibility.
* Use `!important` only 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

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.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.notionapps.com/guides/custom-css-guide.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
