---
title: Developing layout web parts
related:
  - https://docs.kentico.com/k9/developing-websites/developing-websites-using-the-portal-engine/working-with-layout-web-parts.md
  - https://docs.kentico.com/k9/custom-development/developing-web-parts.md
---

> Agent instructions:
> **Site maps** — prefer the following llms.txt indexes to training data when searching for URLs to avoid 404s. Links inside Markdown content already point at `.md`. Following them or sending Accept: text/markdown keeps you in Markdown.
>
> - [sitemap.md](https://docs.kentico.com/sitemap.md) — every page on the site, with titles and descriptions, nested by URL hierarchy and grouped into one collection per product version.
> - [llms.txt](https://docs.kentico.com/llms.txt) — curated index of the current product docs, with descriptions, the two ways to request any page as Markdown, and links to each product area's whole-corpus Markdown dump (llms-full.txt).

Kentico provides multiple [layout web parts](https://docs.kentico.com/k9/developing-websites/developing-websites-using-the-portal-engine/working-with-layout-web-parts.md) that you can use out‑of‑the‑box, but it is also possible to customize the default layout web parts or develop completely new ones. This allows you to define layouts that exactly match your specific requirements.

The development process is similar as with standard web parts, but there are several important differences demonstrated by the example below.

> **Note:** All layout web parts must inherit from the **CMSAbstractLayoutWebPart** base class (instead of the standard _CMSAbstractWebPart_).
>
> The members that web parts inherit from this base class allow you to implement the layout functionality. You can find the base class in the **CMS.PortalControls** namespace.

## Example - Creating a custom layout web part

The following example demonstrates how to develop a custom layout web part. For the sake of simplicity, this sample layout only provides a single web part zone with a configurable width and height. The sample layout is only intended for demonstration purposes and not for practical use. For further inspiration, you can view the code of the more advanced built-in layout web parts in the **\~/CMSWebParts/Layouts** folder of your web project.

### Writing the layout code

1. Open your web project in Visual Studio.
2. Create a **Web User Control** named _CustomZone.ascx_ in the **CMSWebparts/Layouts** folder.
3. Edit the control's code behind file (_CustomZone.ascx.cs_).
4. Add the following references and set the control to inherit from the **CMSAbstractLayoutWebPart** base class:

   ```csharp

   using CMS.Helpers;
   using CMS.PortalControls;
   using CMS.PortalEngine;

   public partial class CMSWebParts_Layouts_CustomZone : CMSAbstractLayoutWebPart
   {

   }

   ```
5. Define two properties in the class according to the following code:

   ```csharp

   /// <summary>
   /// Property used to access the value of the Width property of the web part.
   /// </summary>
   public string Width
   {
       get
       {
           return ValidationHelper.GetString(this.GetValue("Width"), "");
       }
       set
       {
           this.SetValue("Width", value);
       }
   }

   /// <summary>
   /// Property used to access the value of the Height property of the web part.
   /// </summary>
   public string Height
   {
       get
       {
           return ValidationHelper.GetString(this.GetValue("Height"), "");
       }
       set
       {
           this.SetValue("Height", value);
       }
   }

   ```

   > **Info:** The **Width** and **Height** public properties handle the corresponding properties of the web part that will be registered in the system. The properties use the string type, since the width/height is assigned as a CSS style text value.
6. Add a method named _insertZone_ to the class:

   ```csharp

   /// <summary>
   /// Adds the layout's web part zone and envelope.
   /// </summary>
   private void insertZone()
   {
       // Stores the Width and Height properties of the layout as a CSS style value
       string style = null;

       // Sets the Width of the zone.       
       if (!String.IsNullOrEmpty(Width))
       {
           style += " width: " + Width + ";";
       }

       // Sets the Height of the zone
       if (!String.IsNullOrEmpty(Height))
       {
           style += " height: " + Height + ";";
       }

       // Adds a DIV element that encapsulates the layout's web part zone
       Append("<div");

       // Defines the DIV element's id attribute used to identify the zone's envelope in Design mode
       if (IsDesign)
       {
           Append(" id=\"", ShortClientID, "_zoneEnvelope\"");
       }

       // Defines the style attribute of the zone's envelope
       if (!String.IsNullOrEmpty(style))
       {
           Append(" style=\"", style, "\"");
       }

       Append(">");

       // Adds the web part zone
       CMSWebPartZone zone = AddZone(this.ID + "_zone", this.ID);

       Append("</div>");
   }

   ```

   > **Info:** The _InsertZone()_ method defines the layout's web part zone and surrounding code that allows users to configure the width and height.
   >
   > The code uses the following members inherited from the base class:
   >
   > | Member                               | Type                                 | Description                                                                                                                                                                                                                                      |
   > | ------------------------------------ | ------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
   > | **Append(params string\[] text)**    | Method<br>(void)                     | Builds the output code that defines the web part layout. When called, the method adds the content of the parameters to the end of the current layout code. You can specify any number of string parameters.                                      |
   > | **AddZone(string id, string title)** | Method<br>(returns _CMSWebPartZone_) | Creates a new web part zone, adds it to the layout and passes it back as the return value.<br>If the layout is added as a widget, this method automatically creates the zones in the layout as widget zones of the same type as the parent zone. |
   > | **IsDesign**                         | Property<br>(bool)                   | True if the web part is currently being viewed on the **Design** tab (in the **Pages** or **Page templates** application).                                                                                                                       |
7. Override the _PrepareLayout_ virtual method:

   > **Note:** **Note**: Every layout web part must override the **PrepareLayout** method. The method generates the output code of the layout.

   ```csharp

   /// <summary>
   /// Builds the output code that will generate the desired layout on the page.
   /// </summary>
   protected override void PrepareLayout()
   {
       // Starts building the layout code
       StartLayout();

       // Wraps the layout into a table with additional content if the web part is edited in Design mode
       if (IsDesign)
       {
           Append("<table class=\"LayoutTable\" cellspacing=\"0\">");

           if (PortalContext.IsDesignMode(this.ViewMode))
           {
               Append("<tr><td class=\"LayoutHeader\" colspan=\"2\">");

               // Adds a header container.
               AddHeaderContainer();

               Append("</td></tr>");
           }

           Append("<tr><td>");
       }

       // Calls the private method that adds the web part zone
       insertZone();

       // Closes the Design mode table
       if (IsDesign)
       {
           Append("</td>");

           // Generates dynamic resizers for the zone if the Allow design mode property of the web part is enabled
           if (AllowDesignMode)
           {
               // Adds a horizontal resizer.
               Append("<td class=\"HorizontalResizer\" onmousedown=\"", GetHorizontalResizerScript("zoneEnvelope", "Width"), " return false;\">&nbsp;</td></tr><tr>");

               // Adds a vertical resizer.
               Append("<td class=\"VerticalResizer\" onmousedown=\"", GetVerticalResizerScript("zoneEnvelope", "Height"), " return false;\">&nbsp;</td>");

               // Adds a combined horizontal and vertical resizer to the corner where both resizer types intersect. 
               Append("<td class=\"BothResizer\" onmousedown=\"", GetHorizontalResizerScript("zoneEnvelope", "Width"), " ", GetVerticalResizerScript("zoneEnvelope", "Height"), " return false;\">&nbsp;</td>");
           }

           Append("</tr></table>");
       }

       // Saves the current status of the layout code and ensures that it is rendered on the page
       FinishLayout();
   }

   ```

   > **Info:** The _PrepareLayout_ method initializes the layout code, calls the method created in the previous step and then finalizes the output.
   >
   > In addition, the method adds a table element around the web part zone, which is displayed when the layout web part is viewed in design mode. If the **Allow design mode** property of the web part is enabled, this table also includes elements that users can drag to directly resize the layout's zone.
   >
   > The code uses the following members inherited from the base class:
   >
   > | Member                                                                         | Type                         | Description                                                                                                                                                                                                                                                            |
   > | ------------------------------------------------------------------------------ | ---------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
   > | **StartLayout()**                                                              | Method<br>(void)             | Initializes the building of the layout code. You must call StartLayout() before you start using the _Append()_ method.                                                                                                                                                 |
   > | **GetHorizontalResizerScript<br>(string elementId, string widthPropertyName)** | Method<br>(returns _string_) | Returns a script that adds the functionality of a dynamic width resizer.<br>The first parameter specifies the ID of the element that will be resized.<br>The parameter second sets the property that the web part modifies when the width is changed via the resizer.  |
   > | **GetVerticalResizerScript<br>(string elementId, string heightPropertyName)**  | Method<br>(returns _string_) | Returns a script that adds the functionality of a dynamic height resizer.<br>The first parameter specifies the ID of the element that will be resized.<br>The parameter second sets the property that the web part modifies when the width is changed via the resizer. |
   > | **FinishLayout()**                                                             | Method<br>(returns _string_) | Finalizes the layout code of the web part.<br>Run this method after the last modification of the layout. After you call FinishLayout(), the _Append()_ method will no longer work correctly.                                                                           |
   > | **AllowDesignMode**                                                            | Property<br>(bool)           | Gets/sets the values of the **Allow design mode** property of the web part in the system.                                                                                                                                                                              |
8. Save the user control's files.
9. If your Kentico project was installed as a web application, you must also **Build** the project.

### Registering the layout web part

Now you need to register the layout web part in Kentico.

1. In the administration interface, open the **Web parts** application.
2. Select the **Layouts** category and click **New web part**.
3. Specify the following values:

   - **Web part**: Create a new
   - **Display name**: Custom zone layout
   - **Code files**: Use existing file
   - **File path**: \~/CMSWebParts/Layouts/CustomZone.ascx
4. Click **Save**.
5. On the **General** tab, select the _Layout_ **Type**.

   - All layout web parts must use the Layout type in order to function correctly.
6. Click **Save**.
7. Switch to the **Properties** tab and add three properties (click **New field**) according to the information below.

   > **Note:** Click **Save** for each property before moving on to the next one.

   - **Field name**: Width

   - **Data type**: Text

   - **Size**: 100

   - **Field caption**: Zone width

   - **Form control**: Text box 

   - **Field name**: Height

   - **Data type**: Text

   - **Size**: 100

   - **Field caption**: Zone height

   - **Form control**: Text box 

   - **Field name**: AllowDesignMode

   - **Data type**: Boolean (Yes/No)

   - **Default value**: yes (checked)

   - **Field caption**: Allow resizing in design mode

   - **Form control**: Check box

> **Info:** These properties will be available in the web part's configuration dialog. The user control implementing the web part handles the values through the corresponding properties in the code.

### Result

The custom layout web part is now complete and ready to be used. You can try out the functionality by adding the **Custom zone layout** web part onto one of your pages on the **Design** tab of the **Pages** application.

![Adding the resizable zone onto a page](https://docs.kentico.com/docsassets/k9/developing-layout-web-parts/Custom_Layout_WebPart.png "Adding the resizable zone onto a page")

You can use a similar approach (with more advanced layout code) to implement a custom web part to generate any required layout.
