Home

GridLayout

As the name suggests, GridLayout positions the renderables in its collection in a grid pattern: rows and columns made up of evenly sized cells.

Basic use

By default, the dimensions of GridLayout are [1, 1], meaning there is only one row and one column.

// @famous-block
// @famous-block-option preset famous-0.3.0-globals
var Engine = famous.core.Engine;
var Surface = famous.core.Surface;
var GridLayout = famous.views.GridLayout;

var mainContext = Engine.createContext();

var grid = new GridLayout();

var surface = new Surface({
    content: "I am a Surface",
    size: [undefined, undefined],
    properties: {
        backgroundColor: "red",
        color: "#404040",
        textAlign: 'center'
    }
});

grid.sequenceFrom([surface]);

mainContext.add(grid);

Multi-dimensional grids

GridLayout also has a dimensions options where you can define the number of rows and columns in the grid. In this example, instead of using the default dimensions of [1, 1], we will set the dimensions to be [4, 2] so there are four columns and two rows. Since this will create eight sections, we will have our GridLayout sequence over a collection of eight surfaces.

// @famous-block
// @famous-block-option preset famous-0.3.0-globals
var Engine = famous.core.Engine;
var Surface = famous.core.Surface;
var GridLayout = famous.views.GridLayout;

var mainContext = Engine.createContext();

var grid = new GridLayout({
    dimensions: [4, 2]
});

var surfaces = [];

grid.sequenceFrom(surfaces);

for(var i = 0; i < 8; i++) {
    surfaces.push(new Surface({
        content: "panel " + (i + 1),
        size: [undefined, undefined],
        properties: {
            backgroundColor: "hsl(" + (i * 360 / 8) + ", 100%, 50%)",
            color: "#404040",
            lineHeight: '200px',
            textAlign: 'center'
        }
    }));
}

mainContext.add(grid);

Edge cases

What if there are more renderables in the collection than there are sections in the grid? If, using the previous example as a starter, we don’t create eight surfaces, but instead make fifty, GridLayout will split the space up for eight components and only render the first eight renderables.

// @famous-block
// @famous-block-option preset famous-0.3.0-globals
var Engine = famous.core.Engine;
var Surface = famous.core.Surface;
var GridLayout = famous.views.GridLayout;

var mainContext = Engine.createContext();

var grid = new GridLayout({
    dimensions: [4, 2]
});

var surfaces = [];

grid.sequenceFrom(surfaces);

for(var i = 0; i < 50; i++) {
    surfaces.push(new Surface({
        content: "panel " + (i + 1),
        size: [undefined, undefined],
        properties: {
        backgroundColor: "hsl(" + (i * 360 / 50) + ", 100%, 50%)",
            color: "#404040",
            lineHeight: '200px',
            textAlign: 'center'
        }
    }));
}

mainContext.add(grid);

What if there are fewer renderables in my collection than there are sections in my grid? If we don’t create eight surfaces but instead only make five, GridLayout will split the space up for eight components and leave the unused area blank.

// @famous-block
// @famous-block-option preset famous-0.3.0-globals
var Engine = famous.core.Engine;
var Surface = famous.core.Surface;
var GridLayout = famous.views.GridLayout;

var mainContext = Engine.createContext();

var grid = new GridLayout({
    dimensions: [4, 2]
});

var surfaces = [];
grid.sequenceFrom(surfaces);

for(var i = 0; i < 5; i++) {
 surfaces.push(new Surface({
        content: "panel " + (i + 1),
        size: [undefined, undefined],
        properties: {
            backgroundColor: "hsl(" + (i * 360 / 5) + ", 100%, 50%)",
            color: "#404040",
            lineHeight: '200px',
            textAlign: 'center'
        }
    }));
}

mainContext.add(grid);

Renderables with defined sizes

In all prior examples, the GridLayout’s collection of renderables was an array of surfaces with size [undefined, undefined]. Let’s give a defined size to some of those surfaces.

We can see, in this example, that the GridLayout still divides the space the same as before but because the surfaces have defined size, they keep that size instead of filling their container.

// @famous-block
// @famous-block-option preset famous-0.3.0-globals
var Engine = famous.core.Engine;
var Surface = famous.core.Surface;
var GridLayout = famous.views.GridLayout;

var mainContext = Engine.createContext();

var grid = new GridLayout({
    dimensions: [4, 2]
});

var surfaces = [];
grid.sequenceFrom(surfaces);

for(var i = 0; i < 8; i++) {
    var size = i % 2 ? [undefined, undefined] : [20, 20];

    surfaces.push(new Surface({
        size: size,
        properties: {
            backgroundColor: "hsl(" + (i * 360 / 8) + ", 100%, 50%)",
            color: "#404040",
            lineHeight: '200px',
            textAlign: 'center'
        }
    }));
}

mainContext.add(grid);

GridLayout with modifiers

Up until now, we have been attaching the GridLayout directly to the context. As a result, the grid was taking over the entire area. Instead, if we attach the GridLayout to a modifier with a set size, the GridLayout will now be confined to the size of that modifier. This feature is what makes GridLayout and other Famo.us layout widgets so powerful: they arrange themselves automatically based on the size of their parent.

// @famous-block
// @famous-block-option preset famous-0.3.0-globals
var Engine = famous.core.Engine;
var Surface = famous.core.Surface;
var GridLayout = famous.views.GridLayout;
var StateModifier = famous.modifiers.StateModifier;

var mainContext = Engine.createContext();

var grid = new GridLayout({
    dimensions: [4, 2]
});

var surfaces = [];

grid.sequenceFrom(surfaces);

for(var i = 0; i < 8; i++) {
    surfaces.push(new Surface({
        content: "panel " + (i + 1),
        size: [undefined, undefined],
        properties: {
            backgroundColor: "hsl(" + (i * 360 / 8) + ", 100%, 50%)",
            color: "#404040",
            lineHeight: '100px',
            textAlign: 'center'
        }
    }));
}

var stateModifier = new StateModifier({
    size: [400, 200]
});

mainContext.add(stateModifier).add(grid);

Transitions

GridLayout also has a transition option that defines how the grid responds to changes in sizing and dimension. By default, transition is false, meaning that changes are instantly seen on the next frame of animation. If you instead set a specific transition, those changes will transition based on the function, physics transition, or easing curve provided.

(Note: Depending on the changes, this action very well may lead to a lot of browser repaints. Transitioning size will always trigger repaints.)

// @famous-block
// @famous-block-option preset famous-0.3.0-globals
var Engine = famous.core.Engine;
var Surface = famous.core.Surface;
var GridLayout = famous.views.GridLayout;

var mainContext = Engine.createContext();

var grid = new GridLayout({
    dimensions: [4, 2],
    transition: {
        curve: 'easeInOut',
        duration: 2000
    }
});

var surfaces = [];

grid.sequenceFrom(surfaces);

for(var i = 0; i < 8; i++) {
    surfaces.push(new Surface({
        content: "panel " + (i + 1),
        size: [undefined, undefined],
        properties: {
            backgroundColor: "hsl(" + (i * 360 / 8) + ", 100%, 50%)",
            color: "#404040",
            lineHeight: '100px',
            textAlign: 'center'
        }
    }));
}

mainContext.add(grid);

// Switch the size

var toggle = false;

Engine.on('click', function() {
    if (toggle) {
        grid.setOptions({dimensions: [4, 2]});
    }
    else {
        grid.setOptions({dimensions: [2, 4]});
    }

    toggle = !toggle;
});

Next: Nested Layouts »