Article
0 comment

How to make your web parts responsive to the parent container

The modern experience is responsive by default, but it doesn’t mean that your web part will be. Especially with the new team sites and communication sites, the behaviour of web parts is as tricky as it ever was. Office UI Fabric doesn’t help you to achieve a significant user experience because it is out of their scope and offers only smaller components or full-page scoped methods, but nothing in between as needed as in web parts.

The surrounding design of a web part, for example, is defined by Office UI Fabric and even the grid system is provided by that toolkit.
When you write a web part, you might worry more about how the same web part behaves in different containers already defined by the overall page design in SharePoint.

Time to show you a trick how this container pages optimisation is possible in the SharePoint Framework and show the basics.

To grid or not to grid

When you write a web part, you don’t need to include grid columns at all if you don’t want to break the user experience.

A grid is just for full-width web pages or web application. In SharePoint Framework, when creating a web part, you only build a small component in a defined system. This element you create should look right according to the surrounding container. The following screenshot shows what happens when a grid gets applied directly inside a web part.

Grid system in web parts

I added the red lines and the overlay to make the problems visible. The CSS definition assumes that you can create your grid inside a web part, but this is already defined hierarchical on a higher level in the HTML.

In the first row on the page layout, you see a web part that uses all twelve available grid columns. In this container this use is okay. The problem starts with the second line. In there the first web part uses ten grid columns of only eight and the second web part uses ten grid columns of four grid columns available. This applies in the same way on the third row just in reversed order. On the fourth row finally the ten grid columns live in four grid column cell.
You can compare this to add an Excel Worksheet inside an Excel table, which won’t work at all. In CSS no one hinders you from doing that.

Long story kept short. The definition on the web part only uses 66% of the available space of the outer container. In other words, this doesn’t relate to the grid system of the page at all.
In web parts worry more about the surrounding container and not the grid system at all. The question left unanswered for now is how to refer to the surrounding container.

How to use the parent container

The style sheet definition is, as I pointed out on how to better control CSS class naming, local to your web part. The good thing is you can switch the context, and this allows you to access the parent container. The Office UI Fabric grid system uses a twelve columns grid layout. These twelve columns can be divided only into the following container sizes.

  • 12 Grid columns or full width
  • 6 grid columns or spliced into two halves
  • 4 grid columns or a third of the entire width
  • 2 grid columns or one 1/6 of the whole width
  • 1 grid column or 1/12 of the whole page width

The combination of those gives limited possibilities of combination but yet flexible enough in most cases.

The base setup

The web part code is pretty simple and only contains a div element even without any content.

public render(): void {
     this.domElement.innerHTML = `
         <div class="${styles.sectionTester}"></div>
     `;
}

On this .sectionTester div element I then applied the following SCSS/CSS code.

.sectionTester {
    background-color: $blue;
    height: 5vh;
    color: $white;
    display: flex;
    align-items: center;
    justify-content: center;
    &::after {
        font-weight: bold;
        content: 'This setion use some grid columns';
    }
}

This web part only renders a blue box with white text.

Simple web part – Blue box and white text

Now the web part uses the full width of the page. And this scales appropriately according to the parent container. Let us see how this works in the others. We haven’t used any definition for the grid at all an what we get now is the following layout of the page.

Web parts without grid system

All web parts not follow the grid system and are correctly aligned. The only exception is the three columns in the last row, but this issue is caused by the workbench code and not the web part. So this is nothing to worry about this case.

The next step is to change the design of the web part according to the parent container. For that, we need to play around with the CSS scopes of our web part code.

First try – access global scope

The parent container definition lives at a globals page scope. Our web part is component scoped. Therefore, we need to access the design definition outside of the web part.

The following code snippet in the CSS of the web parts accesses the grid definition of the parent container and colours the background of this cell.

:global{
    .CanvasSection-xl12{
        // Under no circumstances don't try this in production 
        background-color: $red;
    }
}

Through the CSS Modules specific pseudo selector :global we switch the scope explicitly to the page context. The full-width container is defined by the Office UI Fabric style sheet class .CanvasSection-xl12 and there we can apply a background colour. This results in the following design in the workbench.

Full page container with changed background to rad

⚠️️☠️ Under no circumstances don’t try this in production ☠️⚠️
This will change the style for all elements with the same CSS class on a page.

The next step is to find a way to switch to the local web part scope. Luckily. CSS Modules also provides a method for that.

Switch back to web part scoped from the global

For the switch back to be web part scoped again we need to use CSS Modules pseudo-class :local directly inside the global scope.

// switch to global page scope
:global {
// We assume the partent container use 12 columns
    .CanvasSection-xl12 {
        // then we switch to a local scope.
        // DO NOT ADD ANY OTHER STYLE IN HERE
       :local {
          // and use the web part container class
         .sectionTester {
            // finally color the web part background
            background-color: $red;
         }
       }
     }
}

We assume that there is a style sheet class on the parent container that uses all twelve grid columns and inside this, it contains our web part. Through the switch back to the local scope we can use the class .sectionTester again. Our web part owns this style sheet class, and CSS modules already know this class name. For CSS Modules there is no need to auto-postfix the class again. It uses the previously defined post-fix.

Red background only gets applied to web part

This way only web parts in a full-page container get the red background. Made possible through the following compiles CSS.

.sectionTester_8c5f0ce3 {
    background-color: #0078c3;
    height: 5vh;
    color: #fff;
    display: -webkit-box;
    display: -ms-flexbox;
    display: flex;
    -webkit-box-align: center;
    -ms-flex-align: center;
    align-items: center;
    -webkit-box-pack: center;
    -ms-flex-pack: center;
    justify-content: center
}

.sectionTester_8c5f0ce3::after {
    font-weight: 700;
    content: 'This setion use some grid columns'
}
/*
 This is where the magic happens
*/
.CanvasSection-xl12 .sectionTester_8c5f0ce3 {
    background-color: #dd324d
}

Now that the problem solved for one possible set up, it is replicate-able for all the different possibilities.

// switch to global page scope
:global {
    // We assume the partent container use 12 columns
    .CanvasSection-xl12 {
        // then we switch to a local scope.
        // DO NOT ADD ANY OTHER STYLE IN HERE
        :local {
            // and use the web part container class
            .sectionTester {
                // finally color the web part background
                background-color: $red;
            }
        }
    }
    // We assume the partent container use 8 columns
    .CanvasSection-xl8 {
        // then we switch to a local scope.
        // DO NOT ADD ANY OTHER STYLE IN HERE
        :local {
            // and use the web part container class
            .sectionTester {
                // finally color the web part background
                background-color: $green;
                color: black;
            }
        }
    }
    // We assume the partent container use 6 columns
    .CanvasSection-xl6 {
        // then we switch to a local scope.
        // DO NOT ADD ANY OTHER STYLE IN HERE
        :local {
            // and use the web part container class
            .sectionTester {
                // finally color the web part background
                background-color: $bluegreen;
            }
        }
    }
    // We assume the partent container use 4 columns
    .CanvasSection-xl4 {
        // then we switch to a local scope.
        // DO NOT ADD ANY OTHER STYLE IN HERE
        :local {
            // and use the web part container class
            .sectionTester {
                // finally color the web part background
                background-color: $yellow;
                color: black;
            }
        }
    }
}

The source code above colours the web part as follows:

  • 12 grid columns – red
  • 8 grid columns – green
  • 6 grid columns – blue
  • 4 grid columns – yellow

When we now refresh the page on the workbench this result in the following design.

The same web part gets different colours according to parent

I know, this only provides a simple example of how to take the parent grid defined container into account. Colouring web parts might not be such a real-world use case, but at least it shows the method on how to do it.

Finally

At last, when you use this way, make sure you don’t change any style in the page scope. This will break the overall experience of SharePoint. We just use the classes to get a clue on where the web part has been added to. For nothing else than this.

There is a wide range of scenarios this method can be useful. For example, you like to use contact cards in different containers. Sometimes you need to have those in a single column in a four grid columns container vertical aligned.

Sometimes you like to have those horizontal equally distributed. Sometimes you want to have just two contact cards next to each other in an eight grid column container. Instead of writing different web parts with a different design this can all be managed by a single web part. A so-called context responsive web part.

Leave a Reply

Required fields are marked *.


This site uses Akismet to reduce spam. Learn how your comment data is processed.