# Creating a custom block with styling

Source: https://dev.arcxp.com/themes/how-to-guides/creating-a-custom-block-with-styling/

You can extend the built-in styling capabilities of Arc XP blocks to custom blocks within your feature pack. By adding just a few files to your block, the StyleBuilder script will read the styles and automatically incorporate them into the site’s stylesheet.

> **Note:**
> 
> Styles will not be built during a Theme Settings or PageBuilder deployment, so they must be run locally first. After running `npx fusion start` locally, you may upload the bundle for deployment.

## Deciding on creating a custom block

To guide your decision on creating and using a forked / custom block instead of an out-of-the-box block, see:

- [Considerations for forking a block](https://dev.arcxp.com/themes/developer-docs/ejecting-an-arc-block#implications-for-ejecting-a-block/)
- [Deciding when to use an out-of-the-box block versus a custom block](https://dev.arcxp.com/themes/developer-docs/ejecting-an-arc-block#deciding-when-to-use-an-out-of-the-box-block-versus-a-custom-block)

## Creating a custom block

You can create a custom block for any of the available types in PageBuilder Engine: output types, layouts, chains, blocks and content sources. Let’s create a custom block example by generating a new file for displaying social media links in the footer of our site:

/components/features/footer/social-links.jsx

```js
import React, { Component } from 'react'
import { Link } from "@wpmedia/arc-themes-components";

const SocialLinks = (props) => {
  return (
    <ul>
      <li><Link href={}>Facebook</Link></li>
      <li><Link href={}>Twitter</Link></li>
      <li><Link href={}>Instagram</Link></li>
    </ul>
  )
}

SocialLinks.label = 'Social Links'

export default SocialLinks
```

At this point, our block won’t function properly because we haven’t filled in the `href` values for our links. If we knew the URLs we wanted to link to beforehand, we could hardcode them into our component, but we might have multiple sites with different URLs, so hardcoding won’t make sense. In this scenario, we want to use Site Properties to get the social URLs for a specific site in our environment. Let’s imagine we have 3 settings in our `blocks.json` file named `facebookPage`, `twitterUrl` and `instagramUrl` that we want to use:

/components/features/footer/social-links.jsx

```js
import React, { Component } from 'react'
import { useFusionContext } from 'fusion:context'
import getProperties from 'fusion:properties';
import { Link } from "@wpmedia/arc-themes-components";

const SocialLinks = (props) => {
  const { arcSite } = useFusionContext()
  const { facebookPage, twitterUrl, instagramUrl } = getProperties(arcSite)

  return (
    <ul>
      <li><Link href={facebookPage}>Facebook</Link></li>
      <li><Link href={twitterUrl}>Twitter</Link></li>
      <li><Link href={instagramUrl}>Instagram</Link></li>
    </ul>
  )
}

SocialLinks.label = 'Social Links'

export default SocialLinks
```

Here, we’ve added two imports to help us get the [site-specific](#adding-site-specific-styles) URLs we want. The line `import { useFusionContext } from 'fusion:context'` imports the useFusionContext function, which will give us information about what site is currently being requested later on. Then, `import getProperties from 'fusion:properties';` imports the getProperties function, which will look up the specific URLs we’re looking for based on the site name. Now within the component function, we can invoke `const { arcSite } = useFusionContext()` to get the current arcSite that is being requested. We can then use that `arcSitevalue` to look up the URLs we need, like: `const { facebookPage, twitterUrl, instagramUrl } = getProperties(arcSite)`. Finally, once we have the URLs in hand, we can plug them into their respective spots in our component.

Now our block should use the appropriate URLs defined in the file `blocks.json` to generate links to our social media accounts.

## Folder and file structure for styling

To enable Blocks Styling for your custom block, you’ll need two files: an `_index.scss` file to define tokens for your block, and a JSON file to store the style definitions. The JSON file should be placed in a themes folder within your block and must be named to match the theme specified in the `blocks.json` file — typically, this theme is set to `news`.

This styling approach is not limited to custom blocks. You can use this structure to create styling tokens for custom chains, layouts, output-types, or any other custom folder nested under `components`.

Your block’s folder structure goes from something like this:

- Directorycomponents  
  - Directoryfeatures  
    - Directorymy-custom-block  
      - default.jsx

to this:

- Directorycomponents  
  - Directoryfeatures  
    - Directorymy-custom-block  
      - \_index.scss
      - default.jsx
      - Directorythemes  
        - news.json
  - Directorychains (example/optional)  
    - Directorymy-custom-chain  
      - \_index.scss
      - default.jsx
      - Directorythemes  
        - news.json
  - Directorylayouts (example/optional)  
    - …etc
  - Directoryoutput-types (example/optional)  
    - …etc
  - Directorycustom-folder (example/optional)  
    - …etc

Normally, including styles in your block requires an `import` statement pointing to the style file’s location. However, with the Blocks Styling approach, this step is not needed.

## Creating tokens

With the necessary files and folders created, you can begin to create tokens that Blocks Styling uses to apply the desired styles. At the top of the new `_index.scss`, you must include the statement `@use "@wpmedia/arc-themes-components/scss";` to import our SCSS library’s mix-ins to process the tokens that it adds in a future step. To add a new token, create a SCSS rule and add `@include scss.block-components("my-block-token");` and `@include scss.block-properties("my-block-token");`. The top level rule should be targeting a class on the outermost wrapper of your block.

Your `_index.scss` should now look something like this:

/components/features/my-custom-block/\_index.scss

```scss
@use "@wpmedia/arc-themes-components/scss";
.my-block-wrapper {
  @include scss.block-components("my-block");
  @include scss.block-properties("my-block");
}
```

Tokens can be added to any valid SCSS rule, but grouping them under a single top-level rule helps avoid styling scope issues. Be careful not to redefine existing tokens. You can also target pseudo-elements by creating tokens specifically for them. A more complete `_index.scss` file might look like this:

/components/features/my-custom-block/\_index.scss

```scss
@use "@wpmedia/arc-themes-components/scss";
.my-block-wrapper {
  @include scss.block-components("my-block");
  @include scss.block-properties("my-block");

  &-left-container {
    @include scss.block-components("my-block-left");
    @include scss.block-properties("my-block-left");

    &:before {
      @include scss.block-components("my-block-left-before");
      @include scss.block-properties("my-block-left-before");
    }
  }
}
```

With that, you now have some tokens defined, and you can move on to adding styles.

## Adding styles to tokens

Now we can start adding styles to the `themes/[my-theme].json`. This JSON file includes an entry on the root node for each token you created. Using the example `_index.scss` from the previous section, the skeleton of the JSON file would look like this:

/components/features/my-custom-block/themes/my-theme.json

```json
{
  "my-block": {
    "styles": {
      "default": {},
      "desktop": {}
    }
  },
  "my-block-left": {
    "styles": {
      "default": {},
      "desktop": {}
    }
  },
  "my-block-left-before": {
    "styles": {
      "default": {},
      "desktop": {}
    }
  }
}
```

In this example, the `default` and `desktop` entries refer to breakpoints. These two breakpoints are provided out of the box in Themes (see [Breakpoints](https://dev.arcxp.com/themes/developer-docs/introduction-to-themes-design-system/#breakpoints) for how to define custom breakpoints). For each breakpoint, you define styles by listing CSS properties within the corresponding object and assigning appropriate values. For example:

/components/features/my-custom-block/themes/my-theme.json

```json
{
  "my-block": {
    "styles": {
      "default": {
        "display": "block"
      },
      "desktop": {
        "display": "flex"
      }
    }
  },
  ...
}
```

The values could also be the global and alias tokens made available in Blocks Styling:

/components/features/my-custom-block/themes/my-theme.json

```json
{
  "my-block": {
    "styles": {
      "default": {
        "color": "$global.neutral-4",
        "display": "block",
        "font-family": "$alias.font-family-secondary"
      },
      "desktop": {
        "display": "flex"
      }
    }
  },
  ...
}
```

> **Note:**
> 
> Only the `default` breakpoint is required and you do not need to include the keys for other breakpoints if you are not adding styling to them.

If you are using components from `@wpmedia/arc-themes-components` in your custom block, you can style those directly without the need for extra tokens. To style those components, use the `component` key in your JSON file. For example, in your block’s output, use the `<Paragraph>` component to output some text. You can style that component like this:

/components/features/my-custom-block/themes/my-theme.json

```json
{
  "my-block": {
    "styles": {
      "default": {
        "color": "$global.neutral-4",
        "display": "block",
        "font-family": "$alias.font-family-secondary",
        "components": {
          "paragraph": {
            "margin-block-end": "$global.spacing-4"
          }
        }
      },
      "desktop": {
        "display": "flex"
      }
    }
  },
  ...
}
```

This code sample styles all uses of the `<Paragraph>` component used within your blocks wrapper. Placing these styles in other tokens affects only the uses of those components within that tokens scope. If you want a larger margin on just the `<Paragraph>` components in the `.my-block-wrapper-left-container` we defined a token for earlier, we could do so like this:

/components/features/my-custom-block/themes/my-theme.json

```json
{
  "my-block": {
    "styles": {
      "default": {
        "color": "$global.neutral-4",
        "display": "block",
        "font-family": "$alias.font-family-secondary",
        "components": {
          "paragraph": {
            "margin-block-end": "$global.spacing-4"
          }
        }
      },
      "desktop": {
        "display": "flex"
      }
    }
  },
  "my-block-left": {
    "styles": {
      "default": {
        "components": {
          "paragraph": {
            "margin-block-end": "$global.spacing-6"
          }
        }
      },
      "desktop": {}
    }
  },
}
```

The `<Paragraph>` component is just an example. You can use this method with any of the component tokens listed in the [Styling](https://dev.arcxp.com/themes/developer-docs/introduction-to-themes-design-system/#styling) section if you use those components in your block’s code.

## Adding site-specific styles

You may want to utilize different styles per site. To achieve this, add a site specific style for your block/component combination. Here’s a code example of a basic custom block:

/components/link-block/default.jsx

```js
import React from 'react';
import { Link } from "@wpmedia/arc-themes-components";

const BLOCK_CLASS_NAME = "b-custom-link-block";

function CustomBlockWithLink() {
  return (
    <div className={ BLOCK_CLASS_NAME }>
      <Link href={}>Click for other reward</Link>
    </div>
  )
}

CustomBlockWithLink.icon = "user-question";
CustomBlockWithLink.label = "My Custom Block With A Link";

export default CustomBlockWithLink;
```

Set up the tokens for this block

/components/link-block/\_index.scss

```scss
@use "@wpmedia/arc-themes-components/scss";
.b-custom-link-block {
  @include scss.block-components("my-custom-block-token");
  @include scss.block-properties("my-custom-block-token");
}
```

Set a default style:

/components/link-block/themes/news.json

```json
{
  "my-custom-block-token": {
    "styles": {
      "default": {
        "components": {
          "link": {
            "text-decoration": "none"
          }
        }
      }
    }
  }
}
```

In order to set a site specific style, add the following file (or append the existing file):

/themes/sites/siteId/styles/blocks.json

```json
{
  "my-custom-block-token": {
    "styles": {
      "default": {
        "components": {
          "link": {
            "text-decoration": "underline"
          }
        }
      }
    }
  }
}
```

For more details on Blocks Styling, see [Introduction to Themes design system](https://dev.arcxp.com/themes/developer-docs/introduction-to-themes-design-system).

## Variants and custom tokens

In addition to creating styles for your custom blocks, you can also create variations of non-custom blocks by creating tokens for certain SCSS rules. To start, add a `customTokens` folder to your feature pack, along with an `_index.scss` and a `themes/[my-theme].json` file. Your feature pack should look something like this:

- blocks.json
- Directorycomponents  
  - features
  - DirectorycustomTokens  
    - \_index.scss
    - Directorythemes  
      - news.json
- content
- …etc

With that set up, you can create new tokens for out-of-the-box blocks. By adding a rule for a block’s class in this new SCSS file, you can then style it specifically based on its location in a layout, if it’s in a specific chain, or if it’s the last instance of a block in the same container.

For example, if you wanted to change the font size of the Card List Block’s title but only on desktop and if it’s in the `rightrail` section of the default Right Rail - Arc Layout, you could do so. Inspecting the Card list block, you can see the title has the class `b-card-list__title`. Then checking the right rail section of the Right Rail layout, you can see it has the class `b-right-rail__main-right-rail`. Knowing this, you can now create a token in the `customTokens/_index.scss`:

/components/customTokens/\_index.scss

```scss
.b-right-rail {
  &__main-right-rail {
    .b-card-list {
      &__title {
        @include scss.block-components("card-list-title-right-rail");
        @include scss.block-properties("card-list-title-right-rail");
      }
    }
  }
}
```

With the token created, you can style it in the `customTokens/themes/[my-theme].json`:

/components/customTokens/themes/my-theme.json

```json
{
  "card-list-title-right-rail": {
    "styles": {
      "default": {},
      "desktop": {
        "font-size": "$global.font-size-5"
      }
    }
  }
}
```

You’ve now created a variant of an out-of-the-box block, without the need to eject and fork the block. There are countless ways to use this functionality — this is just one example.

As noted above, ensure you run your bundle locally first to build the styles and re-upload your bundle with the applied changes for your deployment.

Lastly, if you do have custom code that adds classes conditionally to a page, template, or is a custom-built chain, then you can create variants of out-of-the-box blocks based on those classes here as well. The only difference from the previous example is that you would use those custom classes in targeting a block.
