Skin 10.x: Migrating to Grid

Last modified by Vincent Massol on 2024/11/19 16:15

 XWiki
 Implementation
 Idea

Description

The purpose of this investigation is to evaluate the difficulties, advantages and implementability of switching from Bootstrap to a Grid defined skin.

Comparison

Layout Definition

This is an example of how we have / could have the current layout variations defined in Flamingo skin using multiple techniques:

Limitations

  1. CSS Variables need to be inside a :root {} or other selector declaration, compared to LESS variables that are top level
  2. ErrorBug Cannot use CSS variables inside our .LESS files. Gets a Less4jException: Could not compile less error. 
  3. ErrorLimitation

    Cannot use fr units in calc(). In the demo I'm using px, but we would need to calculated in % for panels sizes, using the formula:
    the width of each column = (width of viewport / number of columns) * 1%

Layout Variations

currentLayout.png

LESS + Bootstrap 3 mixins

@main-padding: @grid-gutter-width * 2;

#body {
  // Both left and right panels are displayed
  &.content {
    // Left panels are small
    &.panel-left-width-Small {
      .main {
        .make-md-column-push(1);
      }
      // Left panels are small and right panels are small
      &.panel-right-width-Small {
        .main {
          .make-md-column(10, @main-padding);
        }
        #leftPanels {
          .make-md-column-pull(10);
        }
      }
      // Left panels are small and right panels are medium
      &.panel-right-width-Medium {
        .main {
          .make-md-column(9, @main-padding);
        }
        #leftPanels {
          .make-md-column-pull(9);
        }
      }
      // Left panels are small and right panels are large
      &.panel-right-width-Large {
        .main {
          .make-md-column(8, @main-padding);
        }
        #leftPanels {
          .make-md-column-pull(8);
        }
      }
    }
    // Left panels are medium
    &.panel-left-width-Medium {
      .main {
        .make-md-column-push(2);
      }
      // Left panels are medium and right panels are small
      &.panel-right-width-Small {
        .main {
          .make-md-column(9, @main-padding);
        }
        #leftPanels {
          .make-md-column-pull(9);
        }
      }
      // Left panels are medium and right panels are medium
      &.panel-right-width-Medium {
        .main {
          .make-md-column(8, @main-padding);
        }
        #leftPanels {
          .make-md-column-pull(8);
        }
      }
      // Left panels are medium and right panels are large
      &.panel-right-width-Large {
        .main {
          .make-md-column(7, @main-padding);
        }
        #leftPanels {
          .make-md-column-pull(7);
        }
      }
    }
    // // Left panels are large
    &.panel-left-width-Large {
      .main {
        .make-md-column-push(3);
      }
      // Left panels are large and right panels are small
      &.panel-right-width-Small {
        .main {
          .make-md-column(8, @main-padding);
        }
        #leftPanels {
          .make-md-column-pull(8);
        }
      }
      // Left panels are large and right panels are medium
      &.panel-right-width-Medium {
        .main {
          .make-md-column(7, @main-padding);
        }
        #leftPanels {
          .make-md-column-pull(7);
        }
      }
      // Left panels are large and right panels are large
      &.panel-right-width-Large {
        .main {
          .make-md-column(6, @main-padding);
        }
        #leftPanels {
          .make-md-column-pull(6);
        }
      }
    }
  }

  // Only right panels
  &.hideleft {
    &.panel-right-width-Small {
      .main {
        .make-md-column(11, @main-padding);
      }
    }
    &.panel-right-width-Medium {
      .main {
        .make-md-column(10, @main-padding);
      }
    }
    &.panel-right-width-Large {
      .main {
        .make-md-column(9, @main-padding);
      }
    }
  }

  // Only left panels
  &.hideright {
    &.panel-left-width-Small {
      .main {
        .make-md-column(11, @main-padding);
        .make-md-column-push(1);
      }
      #leftPanels {
        .make-md-column-pull(11);
      }
    }
    &.panel-left-width-Medium {
      .main {
        .make-md-column(10, @main-padding);
        .make-md-column-push(2);
      }
      #leftPanels {
        .make-md-column-pull(10);
      }
    }
    &.panel-left-width-Large {
      .main {
        .make-md-column(9, @main-padding);
        .make-md-column-push(3);
      }
      #leftPanels {
        .make-md-column-pull(9);
      }
    }
  }

  // No Panels
  &.hidelefthideright {
    .main {
      .make-md-column(12, @main-padding);
    }
  }

  &.panel-left-width-Small {
    #leftPanels {
      .make-md-column(1);
    }
  }
  &.panel-left-width-Medium {
    #leftPanels {
      .make-md-column(2);
    }
  }
  &.panel-left-width-Large {
    #leftPanels {
      .make-md-column(3);
    }
  }
  &.panel-right-width-Small {
    #rightPanels, #editPanels {
      .make-md-column(1);
    }
  }
  &.panel-right-width-Medium {
    #rightPanels, #editPanels {
      .make-md-column(2);
    }
  }
  &.panel-right-width-Large {
    #rightPanels, #editPanels {
      .make-md-column(3);
    }
  }
}

#leftPanels, #rightPanels {
  .make-xs-column(12);
}

LESS + Grid

@supports (display: grid) {
  #contentcolumn {
    grid-area: content;
  }
  #leftPanels {
    grid-area: leftpanels;
  }
  #rightPanels {
    grid-area: rightpanels;
  }
  #contentcontainer {
    display: grid;
    grid: "leftpanels content rightpanels" / auto auto auto;
  }
  body {
    &.panel-left-width-Small.panel-right-width-Small {
      #contentcontainer {
        grid-template-columns: 1fr 10fr 1fr;
      }
    }
    &.panel-left-width-Small.panel-right-width-Medium {
      #contentcontainer {
        grid-template-columns: 1fr 9fr 2fr;
      }
    }
    &.panel-left-width-Small.panel-right-width-Large {
      #contentcontainer {
        grid-template-columns: 1fr 8fr 3fr;
      }
    }
    &.panel-left-width-Medium.panel-right-width-Small {
      #contentcontainer {
        grid-template-columns: 2fr 9fr 1fr;
      }
    }
    &.panel-left-width-Medium.panel-right-width-Medium {
      #contentcontainer {
        grid-template-columns: 2fr 8fr 2fr;
      }
    }
    &.panel-left-width-Medium.panel-right-width-Large {
      #contentcontainer {
        grid-template-columns: 2fr 7fr 3fr;
      }
    }
    &.panel-left-width-Large.panel-right-width-Small {
      #contentcontainer {
        grid-template-columns: 3fr 8fr 1fr;
      }
    }
    &.panel-left-width-Large.panel-right-width-Medium {
      #contentcontainer {
        grid-template-columns: 3fr 7fr 2fr;
      }
    }
    &.panel-left-width-Large.panel-right-width-Large {
      #contentcontainer {
        grid-template-columns: 3fr 6fr 3fr;
      }
    }
    &.hideright {
      &.panel-left-width-Small {
        #contentcontainer {
          grid-template-columns: 1fr 11fr 0;
        }
      }
      &.panel-left-width-Medium {
        #contentcontainer {
          grid-template-columns: 2fr 10fr 0;
        }
      }
      &.panel-left-width-Large {
        #contentcontainer {
          grid-template-columns: 3fr 9fr 0;
        }
      }
    }
    &.hideleft {
      &.panel-right-width-Small {
        #contentcontainer {
          grid-template-columns: 0 11fr 1fr;
        }
      }
      &.panel-right-width-Medium {
        #contentcontainer {
          grid-template-columns: 0 10fr 2fr;
        }
      }
      &.panel-right-width-Large {
        #contentcontainer {
          grid-template-columns: 0 9fr 3fr;
        }
      }
    }
  }
  #body {
    &.hidelefthideright {
      #contentcontainer {
        grid-template-columns: 0 12fr 0;
      }
    }
  }
}

CSS + Grid + CSS Variables

@supports (display: grid) {
  #contentcolumn {
    grid-area: content;
  }
  #leftPanels {
    grid-area: leftpanels;
  }
  #rightPanels {
    grid-area: rightpanels;
  }
  #contentcontainer {
    display: grid;
    grid: "leftpanels content rightpanels" / auto auto auto;
  }
  :root {
    --grid-small-column: 1;
    --grid-medium-column: 2;
    --grid-large-column: 3;
    /* The calculations work good with px, but not with fr. We could adapt to have a % solution */
    --grid-unit: 1fr;
  }
  #body.panel-left-width-Small #contentcontainer {
    --grid-leftPanels: calc(var(--grid-small-column) * var(--grid-unit));
  }
  #body.panel-left-width-Medium #contentcontainer {
    --grid-leftPanels: calc(var(--grid-medium-column) * var(--grid-unit));
  }
  #body.panel-left-width-Large #contentcontainer {
    --grid-leftPanels: calc(var(--grid-large-column) * var(--grid-unit));
  }
  #body.panel-right-width-Small #contentcontainer {
    --grid-rightPanels: calc(var(--grid-small-column) * var(--grid-unit));
  }
  #body.panel-right-width-Medium #contentcontainer {
    --grid-rightPanels: calc(var(--grid-medium-column) * var(--grid-unit));
  }
  #body.panel-right-width-Large #contentcontainer {
    --grid-rightPanels: calc(var(--grid-large-column) * var(--grid-unit));
  }
  #body.hideleft #contentcontainer {
    --grid-leftPanels: 0;
  }
  #body.hideright #contentcontainer {
    --grid-rightPanels: 0;
  }
  #body.hidelefthideright #contentcontainer {
    --grid-leftPanels: 0;
    --grid-rightPanels: 0;
  }
  #contentcontainer {
    --grid-content: auto;
    grid-template-columns: var(--grid-leftPanels) var(--grid-content) var(--grid-rightPanels);
  }
}

 

Get Connected