Skip to content

Instantly share code, notes, and snippets.

@Grezvany13
Last active December 2, 2018 00:13
Show Gist options
  • Save Grezvany13/9b6e5ef4148d4ae7424da94831650185 to your computer and use it in GitHub Desktop.
Save Grezvany13/9b6e5ef4148d4ae7424da94831650185 to your computer and use it in GitHub Desktop.
Lovelace Responsive Container

Lovelace Responsive Container

A simple Lovelace card which allows a more responsive grid for your panels based on Material Design Grid.

Getting Started

Installing

  1. Copy both responsive-container.js and responsive-container.css to your /www/ folder (so they can be accessed through /local/). note At the moment it expect the files to be in /local/custom_cards/responsive-panel/. Modify line 40 in responsive-container.js if the location differs.
  2. Add the module to the resources list:
resources:
  - url: /local/custom_cards/responsive-panel/responsive-container.js
    type: module
  1. Create a page as panel and add the module as type:
views:
  - title: Responsive Container
    id: responsive-container
    panel: true
    cards:
      - type: custom:responsive-container
        cards:
          - ...
  1. Add you own cards to the container
.container {
margin: 0 auto;
width: 100%;
}
.col .row {
margin-left: -0.75rem;
margin-right: -0.75rem;
}
.row {
margin-left: auto;
margin-right: auto;
padding-bottom: 20px;
}
.row:after {
content: "";
display: table;
clear: both;
}
.row .col {
float: left;
-webkit-box-sizing: border-box;
box-sizing: border-box;
padding: 0.75rem;
min-height: 1px;
}
.row .col[class*="push-"], .row .col[class*="pull-"] {
position: relative;
}
.row .col.s1 {
width: 8.3333333333%;
margin-left: auto;
left: auto;
right: auto;
}
.row .col.s2 {
width: 16.6666666667%;
margin-left: auto;
left: auto;
right: auto;
}
.row .col.s3 {
width: 25%;
margin-left: auto;
left: auto;
right: auto;
}
.row .col.s4 {
width: 33.3333333333%;
margin-left: auto;
left: auto;
right: auto;
}
.row .col.s5 {
width: 41.6666666667%;
margin-left: auto;
left: auto;
right: auto;
}
.row .col.s6 {
width: 50%;
margin-left: auto;
left: auto;
right: auto;
}
.row .col.s7 {
width: 58.3333333333%;
margin-left: auto;
left: auto;
right: auto;
}
.row .col.s8 {
width: 66.6666666667%;
margin-left: auto;
left: auto;
right: auto;
}
.row .col.s9 {
width: 75%;
margin-left: auto;
left: auto;
right: auto;
}
.row .col.s10 {
width: 83.3333333333%;
margin-left: auto;
left: auto;
right: auto;
}
.row .col.s11 {
width: 91.6666666667%;
margin-left: auto;
left: auto;
right: auto;
}
.row .col.s12 {
width: 100%;
margin-left: auto;
left: auto;
right: auto;
}
.row .col.offset-s1 {
margin-left: 8.3333333333%;
}
.row .col.pull-s1 {
right: 8.3333333333%;
}
.row .col.push-s1 {
left: 8.3333333333%;
}
.row .col.offset-s2 {
margin-left: 16.6666666667%;
}
.row .col.pull-s2 {
right: 16.6666666667%;
}
.row .col.push-s2 {
left: 16.6666666667%;
}
.row .col.offset-s3 {
margin-left: 25%;
}
.row .col.pull-s3 {
right: 25%;
}
.row .col.push-s3 {
left: 25%;
}
.row .col.offset-s4 {
margin-left: 33.3333333333%;
}
.row .col.pull-s4 {
right: 33.3333333333%;
}
.row .col.push-s4 {
left: 33.3333333333%;
}
.row .col.offset-s5 {
margin-left: 41.6666666667%;
}
.row .col.pull-s5 {
right: 41.6666666667%;
}
.row .col.push-s5 {
left: 41.6666666667%;
}
.row .col.offset-s6 {
margin-left: 50%;
}
.row .col.pull-s6 {
right: 50%;
}
.row .col.push-s6 {
left: 50%;
}
.row .col.offset-s7 {
margin-left: 58.3333333333%;
}
.row .col.pull-s7 {
right: 58.3333333333%;
}
.row .col.push-s7 {
left: 58.3333333333%;
}
.row .col.offset-s8 {
margin-left: 66.6666666667%;
}
.row .col.pull-s8 {
right: 66.6666666667%;
}
.row .col.push-s8 {
left: 66.6666666667%;
}
.row .col.offset-s9 {
margin-left: 75%;
}
.row .col.pull-s9 {
right: 75%;
}
.row .col.push-s9 {
left: 75%;
}
.row .col.offset-s10 {
margin-left: 83.3333333333%;
}
.row .col.pull-s10 {
right: 83.3333333333%;
}
.row .col.push-s10 {
left: 83.3333333333%;
}
.row .col.offset-s11 {
margin-left: 91.6666666667%;
}
.row .col.pull-s11 {
right: 91.6666666667%;
}
.row .col.push-s11 {
left: 91.6666666667%;
}
.row .col.offset-s12 {
margin-left: 100%;
}
.row .col.pull-s12 {
right: 100%;
}
.row .col.push-s12 {
left: 100%;
}
@media only screen and (min-width: 601px) {
.row .col.m1 {
width: 8.3333333333%;
margin-left: auto;
left: auto;
right: auto;
}
.row .col.m2 {
width: 16.6666666667%;
margin-left: auto;
left: auto;
right: auto;
}
.row .col.m3 {
width: 25%;
margin-left: auto;
left: auto;
right: auto;
}
.row .col.m4 {
width: 33.3333333333%;
margin-left: auto;
left: auto;
right: auto;
}
.row .col.m5 {
width: 41.6666666667%;
margin-left: auto;
left: auto;
right: auto;
}
.row .col.m6 {
width: 50%;
margin-left: auto;
left: auto;
right: auto;
}
.row .col.m7 {
width: 58.3333333333%;
margin-left: auto;
left: auto;
right: auto;
}
.row .col.m8 {
width: 66.6666666667%;
margin-left: auto;
left: auto;
right: auto;
}
.row .col.m9 {
width: 75%;
margin-left: auto;
left: auto;
right: auto;
}
.row .col.m10 {
width: 83.3333333333%;
margin-left: auto;
left: auto;
right: auto;
}
.row .col.m11 {
width: 91.6666666667%;
margin-left: auto;
left: auto;
right: auto;
}
.row .col.m12 {
width: 100%;
margin-left: auto;
left: auto;
right: auto;
}
.row .col.offset-m1 {
margin-left: 8.3333333333%;
}
.row .col.pull-m1 {
right: 8.3333333333%;
}
.row .col.push-m1 {
left: 8.3333333333%;
}
.row .col.offset-m2 {
margin-left: 16.6666666667%;
}
.row .col.pull-m2 {
right: 16.6666666667%;
}
.row .col.push-m2 {
left: 16.6666666667%;
}
.row .col.offset-m3 {
margin-left: 25%;
}
.row .col.pull-m3 {
right: 25%;
}
.row .col.push-m3 {
left: 25%;
}
.row .col.offset-m4 {
margin-left: 33.3333333333%;
}
.row .col.pull-m4 {
right: 33.3333333333%;
}
.row .col.push-m4 {
left: 33.3333333333%;
}
.row .col.offset-m5 {
margin-left: 41.6666666667%;
}
.row .col.pull-m5 {
right: 41.6666666667%;
}
.row .col.push-m5 {
left: 41.6666666667%;
}
.row .col.offset-m6 {
margin-left: 50%;
}
.row .col.pull-m6 {
right: 50%;
}
.row .col.push-m6 {
left: 50%;
}
.row .col.offset-m7 {
margin-left: 58.3333333333%;
}
.row .col.pull-m7 {
right: 58.3333333333%;
}
.row .col.push-m7 {
left: 58.3333333333%;
}
.row .col.offset-m8 {
margin-left: 66.6666666667%;
}
.row .col.pull-m8 {
right: 66.6666666667%;
}
.row .col.push-m8 {
left: 66.6666666667%;
}
.row .col.offset-m9 {
margin-left: 75%;
}
.row .col.pull-m9 {
right: 75%;
}
.row .col.push-m9 {
left: 75%;
}
.row .col.offset-m10 {
margin-left: 83.3333333333%;
}
.row .col.pull-m10 {
right: 83.3333333333%;
}
.row .col.push-m10 {
left: 83.3333333333%;
}
.row .col.offset-m11 {
margin-left: 91.6666666667%;
}
.row .col.pull-m11 {
right: 91.6666666667%;
}
.row .col.push-m11 {
left: 91.6666666667%;
}
.row .col.offset-m12 {
margin-left: 100%;
}
.row .col.pull-m12 {
right: 100%;
}
.row .col.push-m12 {
left: 100%;
}
}
@media only screen and (min-width: 993px) {
.row .col.l1 {
width: 8.3333333333%;
margin-left: auto;
left: auto;
right: auto;
}
.row .col.l2 {
width: 16.6666666667%;
margin-left: auto;
left: auto;
right: auto;
}
.row .col.l3 {
width: 25%;
margin-left: auto;
left: auto;
right: auto;
}
.row .col.l4 {
width: 33.3333333333%;
margin-left: auto;
left: auto;
right: auto;
}
.row .col.l5 {
width: 41.6666666667%;
margin-left: auto;
left: auto;
right: auto;
}
.row .col.l6 {
width: 50%;
margin-left: auto;
left: auto;
right: auto;
}
.row .col.l7 {
width: 58.3333333333%;
margin-left: auto;
left: auto;
right: auto;
}
.row .col.l8 {
width: 66.6666666667%;
margin-left: auto;
left: auto;
right: auto;
}
.row .col.l9 {
width: 75%;
margin-left: auto;
left: auto;
right: auto;
}
.row .col.l10 {
width: 83.3333333333%;
margin-left: auto;
left: auto;
right: auto;
}
.row .col.l11 {
width: 91.6666666667%;
margin-left: auto;
left: auto;
right: auto;
}
.row .col.l12 {
width: 100%;
margin-left: auto;
left: auto;
right: auto;
}
.row .col.offset-l1 {
margin-left: 8.3333333333%;
}
.row .col.pull-l1 {
right: 8.3333333333%;
}
.row .col.push-l1 {
left: 8.3333333333%;
}
.row .col.offset-l2 {
margin-left: 16.6666666667%;
}
.row .col.pull-l2 {
right: 16.6666666667%;
}
.row .col.push-l2 {
left: 16.6666666667%;
}
.row .col.offset-l3 {
margin-left: 25%;
}
.row .col.pull-l3 {
right: 25%;
}
.row .col.push-l3 {
left: 25%;
}
.row .col.offset-l4 {
margin-left: 33.3333333333%;
}
.row .col.pull-l4 {
right: 33.3333333333%;
}
.row .col.push-l4 {
left: 33.3333333333%;
}
.row .col.offset-l5 {
margin-left: 41.6666666667%;
}
.row .col.pull-l5 {
right: 41.6666666667%;
}
.row .col.push-l5 {
left: 41.6666666667%;
}
.row .col.offset-l6 {
margin-left: 50%;
}
.row .col.pull-l6 {
right: 50%;
}
.row .col.push-l6 {
left: 50%;
}
.row .col.offset-l7 {
margin-left: 58.3333333333%;
}
.row .col.pull-l7 {
right: 58.3333333333%;
}
.row .col.push-l7 {
left: 58.3333333333%;
}
.row .col.offset-l8 {
margin-left: 66.6666666667%;
}
.row .col.pull-l8 {
right: 66.6666666667%;
}
.row .col.push-l8 {
left: 66.6666666667%;
}
.row .col.offset-l9 {
margin-left: 75%;
}
.row .col.pull-l9 {
right: 75%;
}
.row .col.push-l9 {
left: 75%;
}
.row .col.offset-l10 {
margin-left: 83.3333333333%;
}
.row .col.pull-l10 {
right: 83.3333333333%;
}
.row .col.push-l10 {
left: 83.3333333333%;
}
.row .col.offset-l11 {
margin-left: 91.6666666667%;
}
.row .col.pull-l11 {
right: 91.6666666667%;
}
.row .col.push-l11 {
left: 91.6666666667%;
}
.row .col.offset-l12 {
margin-left: 100%;
}
.row .col.pull-l12 {
right: 100%;
}
.row .col.push-l12 {
left: 100%;
}
}
@media only screen and (min-width: 1201px) {
.row .col.xl1 {
width: 8.3333333333%;
margin-left: auto;
left: auto;
right: auto;
}
.row .col.xl2 {
width: 16.6666666667%;
margin-left: auto;
left: auto;
right: auto;
}
.row .col.xl3 {
width: 25%;
margin-left: auto;
left: auto;
right: auto;
}
.row .col.xl4 {
width: 33.3333333333%;
margin-left: auto;
left: auto;
right: auto;
}
.row .col.xl5 {
width: 41.6666666667%;
margin-left: auto;
left: auto;
right: auto;
}
.row .col.xl6 {
width: 50%;
margin-left: auto;
left: auto;
right: auto;
}
.row .col.xl7 {
width: 58.3333333333%;
margin-left: auto;
left: auto;
right: auto;
}
.row .col.xl8 {
width: 66.6666666667%;
margin-left: auto;
left: auto;
right: auto;
}
.row .col.xl9 {
width: 75%;
margin-left: auto;
left: auto;
right: auto;
}
.row .col.xl10 {
width: 83.3333333333%;
margin-left: auto;
left: auto;
right: auto;
}
.row .col.xl11 {
width: 91.6666666667%;
margin-left: auto;
left: auto;
right: auto;
}
.row .col.xl12 {
width: 100%;
margin-left: auto;
left: auto;
right: auto;
}
.row .col.offset-xl1 {
margin-left: 8.3333333333%;
}
.row .col.pull-xl1 {
right: 8.3333333333%;
}
.row .col.push-xl1 {
left: 8.3333333333%;
}
.row .col.offset-xl2 {
margin-left: 16.6666666667%;
}
.row .col.pull-xl2 {
right: 16.6666666667%;
}
.row .col.push-xl2 {
left: 16.6666666667%;
}
.row .col.offset-xl3 {
margin-left: 25%;
}
.row .col.pull-xl3 {
right: 25%;
}
.row .col.push-xl3 {
left: 25%;
}
.row .col.offset-xl4 {
margin-left: 33.3333333333%;
}
.row .col.pull-xl4 {
right: 33.3333333333%;
}
.row .col.push-xl4 {
left: 33.3333333333%;
}
.row .col.offset-xl5 {
margin-left: 41.6666666667%;
}
.row .col.pull-xl5 {
right: 41.6666666667%;
}
.row .col.push-xl5 {
left: 41.6666666667%;
}
.row .col.offset-xl6 {
margin-left: 50%;
}
.row .col.pull-xl6 {
right: 50%;
}
.row .col.push-xl6 {
left: 50%;
}
.row .col.offset-xl7 {
margin-left: 58.3333333333%;
}
.row .col.pull-xl7 {
right: 58.3333333333%;
}
.row .col.push-xl7 {
left: 58.3333333333%;
}
.row .col.offset-xl8 {
margin-left: 66.6666666667%;
}
.row .col.pull-xl8 {
right: 66.6666666667%;
}
.row .col.push-xl8 {
left: 66.6666666667%;
}
.row .col.offset-xl9 {
margin-left: 75%;
}
.row .col.pull-xl9 {
right: 75%;
}
.row .col.push-xl9 {
left: 75%;
}
.row .col.offset-xl10 {
margin-left: 83.3333333333%;
}
.row .col.pull-xl10 {
right: 83.3333333333%;
}
.row .col.push-xl10 {
left: 83.3333333333%;
}
.row .col.offset-xl11 {
margin-left: 91.6666666667%;
}
.row .col.pull-xl11 {
right: 91.6666666667%;
}
.row .col.push-xl11 {
left: 91.6666666667%;
}
.row .col.offset-xl12 {
margin-left: 100%;
}
.row .col.pull-xl12 {
right: 100%;
}
.row .col.push-xl12 {
left: 100%;
}
}
import {
LitElement, html
} from 'https://unpkg.com/@polymer/lit-element@^0.5.2/lit-element.js?module';
class ResponsiveContainer extends LitElement {
constructor() {
super();
this._cards = [];
this._columns = {
s: 12,
m: 6,
l: 4,
xl: 3
};
}
static get properties() {
return {
hass: Object,
config: Object,
}
}
set hass(hass) {
this._hass = hass;
if(this._cards) {
this._cards.filter(c => typeof c !== 'string').forEach(c => c.hass = hass);
}
}
_render(config) {
const itemTemplates = [];
let columns = {};
for (const card of this._cards) {
if (!!card.config && !!card.config.cols) {
columns = this._calcColumns(this.config.columns, card.config.cols);
} else if (!!card._config && !!card._config.cols) {
columns = this._calcColumns(this.config.columns, card._config.cols);
} else {
columns = this._columns;
}
const className = 'col s' + columns.s + ' m' + columns.m + ' l' + columns.l + ' xl' + columns.xl;
itemTemplates.push(html`<div class$="${className}">${card}</div>`);
}
return html`
<link rel="stylesheet" href="/local/custom_cards/responsive-panel/responsive-container.css">
<style>
</style>
<div class="container">
<div class="row">
${itemTemplates}
</div>
</div>
`;
}
setConfig(config) {
if (!config || !config.cards || !Array.isArray(config.cards)) {
this._cards = [];
return;
}
if (!config || !config.columns) {
config.columns = 6;
this._columns = {
s: 12,
m: 6,
l: 4,
xl: 3
};
}
if (config && config.columns) {
this._columns = this._calcColumns(config.columns);
}
this._cards = config.cards.map((card) => {
if (typeof card === 'string') {
return card;
}
const element = this._createElement(card);
try {
element.setConfig(card);
} catch(err) {}
if (this._hass) {
element.hass = this._hass;
}
return element;
});
this.config = config;
}
_createElement(card) {
let tag = card.type;
if (tag.startsWith("custom:")) {
tag = tag.substr(7);
} else {
tag = `hui-${tag}-card`;
}
return document.createElement(tag);
}
_calcColumns(cols, redo) {
let columns = {
s: 12,
m: 6,
l: 4,
xl: 3
};
redo = parseInt(!!redo ? redo : 1, 10);
cols = parseInt(cols, 10);
const reverse = {
x12: 1,
x6: 2,
x4: 3,
x3: 4,
x2: 6,
x1: 12,
};
if (cols >= 1 && cols <= 12) {
columns = {
s: reverse['x' + Math.ceil(cols/redo/6)],
m: reverse['x' + Math.ceil(cols/redo/4)],
l: reverse['x' + Math.ceil(cols/redo/2)],
xl: reverse['x' + Math.ceil(cols/redo)],
};
}
return columns;
}
getCardSize() {
return this.config.cards.length + 1;
}
}
customElements.define('responsive-container', ResponsiveContainer);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment