Skip to main content

Element Styling

Introduction

Mimeeq Web Components are built using Shadow DOM, providing encapsulation of styles and functionality. To allow for easier customization and styling of these components, we expose various parts that can be targeted and styled using CSS.

The ::part pseudo-element selectors enable developers to style individual parts of Mimeeq Web Components without affecting other parts or the surrounding page. By leveraging these selectors effectively, you can achieve consistent and visually appealing designs across your application.

How Shadow DOM and Parts Work

Understanding Shadow DOM

Shadow DOM creates a separate DOM tree for components, encapsulating their styles and behavior. This provides several benefits:

  1. Style isolation: Styles defined inside the component don't leak out
  2. DOM structure hiding: The internal structure is hidden, providing a clean API
  3. Scoped selectors: CSS selectors inside the component only apply to its shadow tree

However, this encapsulation creates a challenge: how do you customize components from the outside? This is where ::part() comes in.

The ::part() Selector

The ::part() selector provides a controlled way to customize specific elements within Shadow DOM:

  1. Components expose specific elements as "parts" using the part attribute
  2. External styles can target these parts using the ::part() pseudo-element
  3. Only the exposed parts can be styled—the rest remains encapsulated
<!-- Inside the component's shadow DOM -->
<button part="submit-button">Submit</button>

<!-- External CSS -->
mmq-component::part(submit-button) {
background-color: blue;
color: white;
}

Shadow Parts vs. CSS Variables

Mimeeq provides two main methods for styling components:

  1. CSS Variables (Theme Customization):

    • Best for theming (colors, fonts, spacing)
    • Provides a consistent look across all components
    • Easier to maintain with theme changes
  2. Shadow Parts (this guide):

    • Best for structural changes to specific components
    • Allows targeting individual elements within a component
    • Provides more granular control over specific UI elements

For best results, combine both approaches—use CSS variables for theming and parts for specific structural adjustments.

Styling Mimeeq Components with Parts

Entry Point Components

To style Mimeeq components, you'll primarily target these entry point components:

  • mmq-variant-ui: Main container for product variants and customizations
  • mmq-modular-ui: Used for modular UI elements (headers, buttons, etc.)
  • mmq-tabs: Provides tabbed navigation functionality
  • mmq-related-products: Displays related products
  • mmq-basket: Handles shopping cart functionality
  • mmq-dialog: Used for dialog boxes and modals
  • mmq-ar-loader: Handles AR experiences
  • mmq-mobile-tabs: Mobile-specific tabs interface
  • mmq-side-panel: Side panel for options and configurations
  • mmq-ar-preview: Offers augmented reality preview capabilities.

Commonly Styled UI Components

These components are frequently targeted for styling:

  • mmq-button: Button component
  • mmq-tooltip: Tooltip component
  • mmq-loader: Loading indicator component
  • mmq-quick-icon-button: Icon button component
  • mmq-dialog-header: Header for dialog components
  • mmq-dialog-content: Content area for dialog components
  • mmq-dialog-footer: Footer for dialog components

Practical Examples

Example 1: Custom Button Styling

To create buttons with rounded corners, custom colors, and uppercase text:

/* Target the finish button in multiple components */
.mmq-variant-ui::part(finish-btn),
.mmq-mobile-tabs::part(finish-btn) {
border: 1px solid var(--mmq-accent-main);
border-radius: 50px;
text-transform: uppercase;
background: transparent;
color: var(--mmq-accent-main);
flex: unset;
width: auto;
padding: 12px 24px;
font-weight: 600;
transition: all 0.2s ease;
}

/* Add hover effect */
.mmq-variant-ui::part(finish-btn):hover,
.mmq-mobile-tabs::part(finish-btn):hover {
background: var(--mmq-accent-main);
color: white;
}

Example 2: Custom Side Panel Group Styling

To customize option groups in the side panel:

/* Style group headers */
.mmq-variant-ui::part(side-panel-group-header) {
background-color: #f5f5f5;
padding: 12px 16px;
border-left: 3px solid var(--mmq-accent-main);
}

/* Style expanded group items */
.mmq-variant-ui::part(side-panel-group-item-button-expanded) {
font-weight: 700;
text-decoration: underline;
text-underline-offset: 4px;
}

/* Style the content container */
.mmq-variant-ui::part(side-panel-group-content) {
padding: 8px 16px 16px;
background-color: #fafafa;
}

Example 3: Custom Dialog Styling

To create dialogs with rounded corners and custom header:

/* Style dialog header */
.mmq-dialog::part(dialog-header) {
background-color: var(--mmq-accent-main);
color: white;
border-radius: 12px 12px 0 0;
}

/* Style dialog content */
.mmq-dialog::part(dialog-content) {
padding: 24px;
background-color: #f9f9f9;
}

/* Style dialog footer */
.mmq-dialog::part(dialog-footer) {
background-color: #f0f0f0;
padding: 16px 24px;
border-radius: 0 0 12px 12px;
}

/* Style close button */
.mmq-dialog-header::part(close-button) {
color: white;
background-color: rgba(255, 255, 255, 0.2);
border-radius: 50%;
}

Example 4: Customizing Basket Appearance

To reposition the basket button and style it:

/* Position the basket button on the left instead of right */
:root {
--mmq-basket-button-radius: 0px 4px 4px 0;
--mmq-basket-button-position-right: initial;
--mmq-basket-button-position-left: 0;
}

/* Style the basket button */
.mmq-basket::part(button) {
background-color: var(--mmq-accent-main);
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
}

/* Style the counter badge */
.mmq-basket::part(counter) {
background-color: white;
color: var(--mmq-accent-main);
font-weight: bold;
}

/* Adjust the panel position */
.mmq-basket::part(panel) {
--mmq-basket-panel-position-right: unset;
--mmq-basket-panel-position-left: 0;
}

Example 5: Mobile Tabs Customization

To enhance the mobile tabs interface:

/* Style the tab buttons */
.mmq-mobile-tabs::part(tab) {
padding: 12px 16px;
border-bottom: 2px solid transparent;
transition: all 0.2s ease;
}

/* Style active tab */
.mmq-mobile-tabs::part(tab-active) {
border-bottom: 2px solid var(--mmq-accent-main);
font-weight: 700;
}

/* Style tab content wrapper */
.mmq-mobile-tabs::part(content-wrapper) {
padding: 16px;
background-color: #fafafa;
}

Component Part Reference

Below are the key components and their available parts for styling. This is not an exhaustive list, but covers the most commonly styled parts.

For full list of available parts and extensive list of components go to:

mmq-variant-ui

PartDescription
wrapperMain container for the entire UI
canvas-containerContainer for the 3D canvas
side-panelContainer for configuration options
side-panel-headerHeader of the side panel
side-panel-contentContent area of the side panel
side-panel-footerFooter of the side panel
side-panel-groupGroup container in the side panel
side-panel-group-headerHeader for a group in the side panel
side-panel-group-contentContent for a group in the side panel
side-panel-group-item-buttonButton for a group item
side-panel-group-item-button-expandedExpanded state for a group item button
finish-btnThe finish/add to cart button
summary-box-pricePrice display in summary box
price-value-fieldPrice display element on mobile
price-containerContainer for price on mobile

mmq-basket

PartDescription
buttonThe floating basket button
counterThe item counter badge
iconThe icon within the button
panelThe sliding panel for basket contents
backdropThe overlay behind the panel

mmq-dialog-header

PartDescription
titleThe dialog title text
close-buttonThe close button
close-iconThe icon within the close button

mmq-mobile-tabs

PartDescription
listContainer for tab buttons
tabIndividual tab button
tab-activeCurrently active tab
content-wrapperContainer for tab content
footerFooter with actions
finish-btnFinish/cart button in footer
summary-box-pricePrice display element

Best Practices

Ensure Specificity

When styling parts, be specific about which component the part belongs to:

/* Good: Specifically targets the button in mmq-basket */
.mmq-basket::part(button) {
background-color: red;
}

/* Bad: Could conflict with other components that have a button part */
::part(button) {
background-color: red;
}

Combine with CSS Variables

For the most maintainable code, use CSS variables for values that might change:

/* Define theme variables at root */
:root {
--my-brand-color: #ff5722;
--my-border-radius: 8px;
}

/* Use variables when styling parts */
.mmq-variant-ui::part(finish-btn) {
background-color: var(--my-brand-color);
border-radius: var(--my-border-radius);
}

Test Across Browsers

Shadow DOM and the ::part() selector have good support in modern browsers but test your styling in all required browsers.

Fallback for Older Browsers

Consider providing fallbacks for browsers that don't support shadow parts:

/* Fallback using CSS variables for older browsers */
:root {
--mmq-finish-btn-background: blue;
}

/* Modern browsers will use this */
.mmq-variant-ui::part(finish-btn) {
background-color: blue;
}

Handling CSS Resets

When using global CSS resets in your application, you need to be careful not to break Mimeeq components. Here are two approaches:

Method 1: Using the .hydrated Class

Mimeeq automatically adds the .hydrated class to custom elements once loaded:

/* Reset styles for standard elements only */
*:not(.hydrated),
*:not(.hydrated)::before,
*:not(.hydrated)::after {
margin: 0;
box-sizing: inherit;
}

Method 2: Using Attribute Selectors

Target only standard HTML elements for your reset:

/* Reset styles for built-in elements only */
:where(*:not(:defined)):not(:is(*-*)),
:where(*:not(:defined)):not(:is(*-*))::before,
:where(*:not(:defined)):not(:is(*-*))::after {
margin: 0;
box-sizing: inherit;
}

Further Resources