I want to create a monopoly board like . There are following features in the board
The corner are square shaped and bigger than other boxes
The text of each row is facing a specfic angle.
My basic html structure is below
Board
Row 1
Tile 1
Tile 2
...
I am successful in creating the basic structure using grid-template-areas. The problem I am facing is that I can't rotate the tiles of each row according to the need.
I have created a basic snippet which have only 3 tiles per row. The first row is facing right angle all other rows are at wrong angle. 90deg for second row. 180deg for third row. and 270deg for fourth row.
I have tried using writing-mode and transform:rotate() but it doesn't work or maybe I am using it wrong way. Please help me to find the correct way. I will be really thankful
*{
box-sizing: border-box;
}
#board {
display: grid;
/*first and last row and column are bigger than others*/
grid-template-columns: 100px repeat(2, 70px) 100px;
grid-template-rows: 100px repeat(2, 70px) 100px;
/*a, b, c, d are 4 rows and o is center*/
grid-template-areas:
"c c c d"
"b o o d"
"b o o d"
"b a a a";
}
#center {
grid-area: o;
}
.row {
display: flex;
}
.tile {
display: flex;
flex-direction: column;
border: 1px solid;
height: 100%;
width: 100%;
}
.tile-color {
flex: 3;
background: red;
border: 1px solid;
}
.tile-name {
flex: 6;
}
.tile-price {
flex: 3;
}
/*Flex directions are used to give the tiles correct order*/
#row-0 {
grid-area: a;
flex-direction: row-reverse;
}
#row-1 {
grid-area: b;
flex-direction: column-reverse;
}
#row-2 {
grid-area: c;
flex-direction: row;
}
#row-3 {
grid-area: d;
flex-direction: column;
}
/*To make the corner tiles bigger and square*/
.row > .tile:nth-child(1){
flex: 0 0 100px;
}
<div id="board">
<div id="center"></div>
<!--Row 1-->
<div class="row" id="row-0">
<div class="tile">
<div class="tile-name">Go</div>
</div>
<div class="tile">
<div class="tile-color"></div>
<div class="tile-name">Tile 1</div>
<div class="tile-price">Price 1</div>
</div>
<div class="tile">
<div class="tile-color"></div>
<div class="tile-name">Tile 2</div>
<div class="tile-price">Price 2</div>
</div>
</div>
<!--Row 2-->
<div class="row" id="row-1">
<div class="tile">
<div class="tile-name">Just visiting</div>
</div>
<div class="tile">
<div class="tile-color"></div>
<div class="tile-name">Tile 3</div>
<div class="tile-price">Price 3</div>
</div>
<div class="tile">
<div class="tile-color"></div>
<div class="tile-name">Tile 4</div>
<div class="tile-price">Price 4</div>
</div>
</div>
<!--Row 3-->
<div class="row" id="row-2">
<div class="tile">
<div class="tile-name">Free Parking</div>
</div>
<div class="tile">
<div class="tile-color"></div>
<div class="tile-name">Tile 4</div>
<div class="tile-price">Price 4</div>
</div>
<div class="tile">
<div class="tile-color"></div>
<div class="tile-name">Tile 5</div>
<div class="tile-price">Price 5</div>
</div>
</div>
<!--Row 4-->
<div class="row" id="row-3">
<div class="tile">
<div class="tile-name">Jail</div>
</div>
<div class="tile">
<div class="tile-color"></div>
<div class="tile-name">Tile 6</div>
<div class="tile-price">Price 6</div>
</div>
<div class="tile">
<div class="tile-color"></div>
<div class="tile-name">Tile 7</div>
<div class="tile-price">Price 7</div>
</div>
</div>
</div>
Here's one way to do this.
I have changed the HTML markup and haven't used grid-template-areas property. Each grid item is placed in the grid automatically in the order they are placed in the HTML markup.
Its a 4 x 4 grid where first and last columns are 120px in size and middle 2 columns are 75px each. Similarly first and last rows are 120px in size and middle 2 rows are 75px each.
To rotate grid items, i have created individual classes and applied appropriate rotation class on individual grid items which need to be rotated.
* {
box-sizing: border-box;
}
.board {
display: grid;
grid-template-columns: 120px repeat(2, 75px) 120px;
grid-template-rows: 120px repeat(2, 75px) 120px;
justify-content: center;
}
.lg-box {
text-align: center;
background: #999;
border: 1px solid;
overflow: hidden;
}
.sm-box {
width: 100%;
background: blue;
background: red;
height: 100%;
position: relative;
border: 1px solid;
overflow: hidden;
}
.sm-box div {
background: #fff;
height: 85%;
width: 100%;
display: flex;
flex-direction: column;
justify-content: space-between;
text-align: center;
position: absolute;
bottom: 0;
padding: 5px;
}
.lg-box-centered {
background: #fff;
grid-row: 2 / span 2;
grid-column: 2 / span 2;
}
.rot-180 {
transform: rotate(180deg);
}
.lg-rot,
.lg-box-centered {
height: 100%;
display: flex;
align-items: center;
justify-content: center;
}
.rot-135 {
transform: rotate(135deg);
}
.rot-45-reverse {
transform: rotate(-45deg);
}
.rot-45 {
transform: rotate(45deg);
}
.rot-135-reverse {
transform: rotate(-135deg);
}
.rot-90 {
transform: rotate(90deg);
}
.rot-90-reverse {
transform: rotate(-90deg);
}
.sm-box .rot-90,
.sm-box .rot-90-reverse {
position: absolute;
left: 12px;
top: -12px;
width: 75px;
height: 100px;
}
.sm-box .rot-90-reverse {
left: initial;
right: 12px;
}
<div class="board">
<div class="lg-box">
<div class="lg-rot rot-135">Just Visiting</div>
</div>
<div class="sm-box rot-180">
<div>
<span class="title">Title 5</span>
<span class="price">Price 5</span>
</div>
</div>
<div class="sm-box rot-180">
<div>
<span class="title">Title 6</span>
<span class="price">Price 6</span>
</div>
</div>
<div class="lg-box">
<div class="lg-rot rot-135-reverse">Jail</div>
</div>
<div class="sm-box">
<div class="rot-90">
<span class="title">Title 4</span>
<span class="price">Price 4</span>
</div>
</div>
<div class="sm-box">
<div class="rot-90-reverse">
<span class="title">Title 7</span>
<span class="price">Price 7</span>
</div>
</div>
<div class="lg-box-centered">center</div>
<div class="sm-box">
<div class="rot-90">
<span class="title">Title 3</span>
<span class="price">Price 3</span>
</div>
</div>
<div class="sm-box">
<div class="rot-90-reverse">
<span class="title">Title 8</span>
<span class="price">Price 8</span>
</div>
</div>
<div class="lg-box">
<div class="lg-rot rot-45">Just Visiting</div>
</div>
<div class="sm-box">
<div>
<span class="title">Title 2</span>
<span class="price">Price 2</span>
</div>
</div>
<div class="sm-box">
<div>
<span class="title">Title 1</span>
<span class="price">Price 1</span>
</div>
</div>
<div class="lg-box">
<div class="lg-rot rot-45-reverse">Go</div>
</div>
</div>
Here's an alternative approach with 7 x 7 grid and uses writing-mode property. Only difference between this approach and the previous one is that it uses writing-mode property to properly align text within small boxes from row number 2 to row number 6.
* {
box-sizing: border-box;
}
.board {
display: grid;
grid-template-columns: 120px repeat(5, 75px) 120px;
grid-template-rows: 120px repeat(5, 75px) 120px;
justify-content: center;
}
.lg-box {
text-align: center;
background: #999;
border: 1px solid;
overflow: hidden;
}
.sm-box {
width: 100%;
background: blue;
background: red;
height: 100%;
position: relative;
border: 1px solid;
overflow: hidden;
}
.sm-box div {
background: #fff;
height: 85%;
width: 100%;
display: flex;
flex-direction: column;
justify-content: space-between;
text-align: center;
position: absolute;
bottom: 0;
padding: 5px;
}
.lg-box-centered {
background: #fff;
grid-row: 2 / span 5;
grid-column: 2 / span 5;
}
.rot-180 {
transform: rotate(180deg);
}
.lg-rot,
.lg-box-centered {
height: 100%;
display: flex;
align-items: center;
justify-content: center;
}
.rot-135 {
transform: rotate(135deg);
}
.rot-45-reverse {
transform: rotate(-45deg);
}
.rot-45 {
transform: rotate(45deg);
}
.rot-135-reverse {
transform: rotate(-135deg);
}
.sm-box .rot-90,
.sm-box .rot-90-reverse {
height: 75px;
width: 85%;
writing-mode: vertical-rl;
position: absolute;
left: -10px;
}
.sm-box .rot-90-reverse {
transform: rotate(180deg);
right: 10px;
}
<div class="board">
<div class="lg-box">
<div class="lg-rot rot-135">Just Visiting</div>
</div>
<div class="sm-box rot-180">
<div>
<span class="title">Title 11</span>
<span class="price">Price 11</span>
</div>
</div>
<div class="sm-box rot-180">
<div>
<span class="title">Title 12</span>
<span class="price">Price 12</span>
</div>
</div>
<div class="sm-box rot-180">
<div>
<span class="title">Title 13</span>
<span class="price">Price 13</span>
</div>
</div>
<div class="sm-box rot-180">
<div>
<span class="title">Title 14</span>
<span class="price">Price 14</span>
</div>
</div>
<div class="sm-box rot-180">
<div>
<span class="title">Title 15</span>
<span class="price">Price 15</span>
</div>
</div>
<div class="lg-box">
<div class="lg-rot rot-135-reverse">Jail</div>
</div>
<div class="sm-box">
<div class="rot-90">
<span class="title">Title 10</span>
<span class="price">Price 10</span>
</div>
</div>
<div class="sm-box">
<div class="rot-90-reverse">
<span class="title">Title 16</span>
<span class="price">Price 16</span>
</div>
</div>
<div class="sm-box">
<div class="rot-90">
<span class="title">Title 9</span>
<span class="price">Price 9</span>
</div>
</div>
<div class="sm-box">
<div class="rot-90-reverse">
<span class="title">Title 17</span>
<span class="price">Price 17</span>
</div>
</div>
<div class="lg-box-centered">center</div>
<div class="sm-box">
<div class="rot-90">
<span class="title">Title 8</span>
<span class="price">Price 8</span>
</div>
</div>
<div class="sm-box">
<div class="rot-90-reverse">
<span class="title">Title 18</span>
<span class="price">Price 18</span>
</div>
</div>
<div class="sm-box">
<div class="rot-90">
<span class="title">Title 7</span>
<span class="price">Price 7</span>
</div>
</div>
<div class="sm-box">
<div class="rot-90-reverse">
<span class="title">Title 19</span>
<span class="price">Price 19</span>
</div>
</div>
<div class="sm-box">
<div class="rot-90">
<span class="title">Title 6</span>
<span class="price">Price 6</span>
</div>
</div>
<div class="sm-box">
<div class="rot-90-reverse">
<span class="title">Title 20</span>
<span class="price">Price 20</span>
</div>
</div>
<div class="lg-box">
<div class="lg-rot rot-45">Just Visiting</div>
</div>
<div class="sm-box">
<div>
<span class="title">Title 5</span>
<span class="price">Price 5</span>
</div>
</div>
<div class="sm-box">
<div>
<span class="title">Title 4</span>
<span class="price">Price 4</span>
</div>
</div>
<div class="sm-box">
<div>
<span class="title">Title 3</span>
<span class="price">Price 3</span>
</div>
</div>
<div class="sm-box">
<div>
<span class="title">Title 2</span>
<span class="price">Price 2</span>
</div>
</div>
<div class="sm-box">
<div>
<span class="title">Title 1</span>
<span class="price">Price 1</span>
</div>
</div>
<div class="lg-box">
<div class="lg-rot rot-45-reverse">Go</div>
</div>
</div>
Here's a 7 x 7 board using first approach
* {
box-sizing: border-box;
}
.board {
display: grid;
grid-template-columns: 120px repeat(5, 75px) 120px;
grid-template-rows: 120px repeat(5, 75px) 120px;
justify-content: center;
}
.lg-box {
text-align: center;
background: #999;
border: 1px solid;
overflow: hidden;
}
.sm-box {
width: 100%;
background: blue;
background: red;
height: 100%;
position: relative;
border: 1px solid;
overflow: hidden;
}
.sm-box div {
background: #fff;
height: 85%;
width: 100%;
display: flex;
flex-direction: column;
justify-content: space-between;
text-align: center;
position: absolute;
bottom: 0;
padding: 5px;
}
.lg-box-centered {
background: #fff;
grid-row: 2 / span 5;
grid-column: 2 / span 5;
}
.rot-180 {
transform: rotate(180deg);
}
.lg-rot,
.lg-box-centered {
height: 100%;
display: flex;
align-items: center;
justify-content: center;
}
.rot-135 {
transform: rotate(135deg);
}
.rot-45-reverse {
transform: rotate(-45deg);
}
.rot-45 {
transform: rotate(45deg);
}
.rot-135-reverse {
transform: rotate(-135deg);
}
.rot-90 {
transform: rotate(90deg);
}
.rot-90-reverse {
transform: rotate(-90deg);
}
.sm-box .rot-90,
.sm-box .rot-90-reverse {
position: absolute;
left: 12px;
top: -12px;
width: 75px;
height: 100px;
}
.sm-box .rot-90-reverse {
left: initial;
right: 12px;
}
<div class="board">
<div class="lg-box">
<div class="lg-rot rot-135">Just Visiting</div>
</div>
<div class="sm-box rot-180">
<div>
<span class="title">Title 11</span>
<span class="price">Price 11</span>
</div>
</div>
<div class="sm-box rot-180">
<div>
<span class="title">Title 12</span>
<span class="price">Price 12</span>
</div>
</div>
<div class="sm-box rot-180">
<div>
<span class="title">Title 13</span>
<span class="price">Price 13</span>
</div>
</div>
<div class="sm-box rot-180">
<div>
<span class="title">Title 14</span>
<span class="price">Price 14</span>
</div>
</div>
<div class="sm-box rot-180">
<div>
<span class="title">Title 15</span>
<span class="price">Price 15</span>
</div>
</div>
<div class="lg-box">
<div class="lg-rot rot-135-reverse">Jail</div>
</div>
<div class="sm-box">
<div class="rot-90">
<span class="title">Title 10</span>
<span class="price">Price 10</span>
</div>
</div>
<div class="sm-box">
<div class="rot-90-reverse">
<span class="title">Title 16</span>
<span class="price">Price 16</span>
</div>
</div>
<div class="sm-box">
<div class="rot-90">
<span class="title">Title 9</span>
<span class="price">Price 9</span>
</div>
</div>
<div class="sm-box">
<div class="rot-90-reverse">
<span class="title">Title 17</span>
<span class="price">Price 17</span>
</div>
</div>
<div class="lg-box-centered">center</div>
<div class="sm-box">
<div class="rot-90">
<span class="title">Title 8</span>
<span class="price">Price 8</span>
</div>
</div>
<div class="sm-box">
<div class="rot-90-reverse">
<span class="title">Title 18</span>
<span class="price">Price 18</span>
</div>
</div>
<div class="sm-box">
<div class="rot-90">
<span class="title">Title 7</span>
<span class="price">Price 7</span>
</div>
</div>
<div class="sm-box">
<div class="rot-90-reverse">
<span class="title">Title 19</span>
<span class="price">Price 19</span>
</div>
</div>
<div class="sm-box">
<div class="rot-90">
<span class="title">Title 6</span>
<span class="price">Price 6</span>
</div>
</div>
<div class="sm-box">
<div class="rot-90-reverse">
<span class="title">Title 20</span>
<span class="price">Price 20</span>
</div>
</div>
<div class="lg-box">
<div class="lg-rot rot-45">Just Visiting</div>
</div>
<div class="sm-box">
<div>
<span class="title">Title 5</span>
<span class="price">Price 5</span>
</div>
</div>
<div class="sm-box">
<div>
<span class="title">Title 4</span>
<span class="price">Price 4</span>
</div>
</div>
<div class="sm-box">
<div>
<span class="title">Title 3</span>
<span class="price">Price 3</span>
</div>
</div>
<div class="sm-box">
<div>
<span class="title">Title 2</span>
<span class="price">Price 2</span>
</div>
</div>
<div class="sm-box">
<div>
<span class="title">Title 1</span>
<span class="price">Price 1</span>
</div>
</div>
<div class="lg-box">
<div class="lg-rot rot-45-reverse">Go</div>
</div>
</div>
I liked your question, to solve I combined both "transform:rotate()" and "writing-mode:vertical-rl", and I rotated the titles of the corners to stay diagonal!
I just changed what is below the last 2 comments in CSS:
*{
box-sizing: border-box;
}
#board {
display: grid;
/*first and last row and column are bigger than others*/
grid-template-columns: 100px repeat(2, 70px) 100px;
grid-template-rows: 100px repeat(2, 70px) 100px;
/*a, b, c, d are 4 rows and o is center*/
grid-template-areas:
"c c c d"
"b o o d"
"b o o d"
"b a a a";
}
#center {
grid-area: o;
}
.row {
display: flex;
}
.tile {
display: flex;
flex-direction: column;
border: 1px solid;
height: 100%;
width: 100%;
}
.tile-color {
flex: 3;
background: red;
border: 1px solid;
}
.tile-name {
flex: 6;
}
.tile-price {
flex: 3;
}
/*Flex directions are used to give the tiles correct order*/
#row-0 {
grid-area: a;
flex-direction: row-reverse;
}
#row-1 {
grid-area: b;
flex-direction: column-reverse;
}
#row-2 {
grid-area: c;
flex-direction: row;
}
#row-3 {
grid-area: d;
flex-direction: column;
}
/*To make the corner tiles bigger and square*/
.row > .tile:nth-child(1){
flex: 0 0 100px;
}
/*Turn tiles*/
#row-1 .tile{
writing-mode: vertical-rl;
}
#row-2 .tile{
transform: rotate(180deg);
}
#row-3 .tile{
writing-mode: vertical-rl;
transform: rotate(180deg);
}
/*Turn corners*/
.row > .tile:first-child{
text-align: center;
}
#row-0 > .tile:first-child .tile-name{
transform: rotate(-45deg) translateY(38px);
}
#row-1 > .tile:first-child .tile-name{
transform: rotate(-45deg) translateX(-38px);
}
#row-2 > .tile:first-child .tile-name{
transform: rotate(-45deg) translateY(38px);
}
#row-3 > .tile:first-child .tile-name{
transform: rotate(-45deg) translateX(-38px);
}
<div id="board">
<div id="center"></div>
<!--Row 1-->
<div class="row" id="row-0">
<div class="tile">
<div class="tile-name">Go</div>
</div>
<div class="tile">
<div class="tile-color"></div>
<div class="tile-name">Tile 1</div>
<div class="tile-price">Price 1</div>
</div>
<div class="tile">
<div class="tile-color"></div>
<div class="tile-name">Tile 2</div>
<div class="tile-price">Price 2</div>
</div>
</div>
<!--Row 2-->
<div class="row" id="row-1">
<div class="tile">
<div class="tile-name">Just visiting</div>
</div>
<div class="tile">
<div class="tile-color"></div>
<div class="tile-name">Tile 3</div>
<div class="tile-price">Price 3</div>
</div>
<div class="tile">
<div class="tile-color"></div>
<div class="tile-name">Tile 4</div>
<div class="tile-price">Price 4</div>
</div>
</div>
<!--Row 3-->
<div class="row" id="row-2">
<div class="tile">
<div class="tile-name">Free Parking</div>
</div>
<div class="tile">
<div class="tile-color"></div>
<div class="tile-name">Tile 4</div>
<div class="tile-price">Price 4</div>
</div>
<div class="tile">
<div class="tile-color"></div>
<div class="tile-name">Tile 5</div>
<div class="tile-price">Price 5</div>
</div>
</div>
<!--Row 4-->
<div class="row" id="row-3">
<div class="tile">
<div class="tile-name">Jail</div>
</div>
<div class="tile">
<div class="tile-color"></div>
<div class="tile-name">Tile 6</div>
<div class="tile-price">Price 6</div>
</div>
<div class="tile">
<div class="tile-color"></div>
<div class="tile-name">Tile 7</div>
<div class="tile-price">Price 7</div>
</div>
</div>
</div>
I noticed that the "writing-mode" didn’t turn to the other horizontal, so I turned it to the same horizontal and rotated 180º, so it stays in exactly the same position.
I hope I helped you!
Since this question is tagged with #javascript and currently there is no answer using it I decided to give it a go.
I assume that your goal is to make an interactive board game, so there is no avoiding JS.
If your goal is to just render such grid, I also made an attempt to do it almost exclusively in CSS - it means just bunch of divs without any classes or ids and then setting up grid mostly based on :nth-child() pseudo-class.
const TileType = {
TECHNOLOGY: 'technology',
CHANCE: 'chance',
START: 'start',
STACKOVERFLOW: 'stackoverflow',
GO_TO_STACKOVERFLOW: 'goToStackoverflow',
DEBUGGING: 'debugging',
}
const TechnologyType = {
BACKEND: 'backend',
FRONTEND: 'frontend',
MOBILE: 'mobile',
NATIVE: 'native',
}
const ChanceType = {
RED: 'red',
BLUE: 'blue',
}
class Tile {
constructor(title, type, value = null) {
this.title = title;
this.type = type;
this.value = value;
}
toHTML() {
const card = document.createElement('div');
if ( this.title) {
const title = document.createElement('p');
title.classList.add('title');
title.innerText = this.title;
card.appendChild(title);
}
card.addEventListener('click', () => console.log(this));
return card;
}
}
// Still no static props in JS
const technologyColorMap = {
[TechnologyType.BACKEND]: '#2ab7ca',
[TechnologyType.FRONTEND]: '#fed766',
[TechnologyType.MOBILE]: '#7bc043',
[TechnologyType.NATIVE]: '#63ace5',
};
class TechnologyTile extends Tile {
constructor(title, subType, value = null) {
super(title, TileType.TECHNOLOGY, value);
this.technologyType = subType;
}
toHTML() {
const card = super.toHTML();
card.classList.add('technology');
const colorBox = document.createElement('div');
colorBox.classList.add('colorBox');
colorBox.style.backgroundColor = technologyColorMap[this.technologyType];
card.prepend(colorBox);
return card;
}
}
const chanceTypeColorMap = {
[ChanceType.RED]: '#fe4a49',
[ChanceType.BLUE]: '#005b96',
};
class ChanceTile extends Tile {
constructor(title, subType, value = null) {
super(title, TileType.CHANCE, value);
this.chanceType = subType;
}
toHTML() {
const card = super.toHTML();
card.classList.add('chance');
//card.appendChild(this.getIcon());
return card;
}
getIcon() {
const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
svg.classList.add('chance');
svg.setAttributeNS(null,"width","180");
svg.setAttributeNS(null,"height","180");
const path = document.createElementNS('http://www.w3.org/2000/svg',"path");
path.setAttributeNS(null,"d","M60,67c0-13 1-19 8-26c7-9 18-10 28-8c10,2 22,12 22,26c0,14-11,19-15,22c-7,2-10,6-11,11v20m0,12v16");
path.setAttributeNS(null,"fill", "none");
path.setAttributeNS(null,"stroke", chanceTypeColorMap[this.chanceType]);
path.setAttributeNS(null,"stroke-width","6");
svg.appendChild(path);
return svg;
}
}
const tiles = [
new Tile('Start', TileType.START),
new TechnologyTile('Java Spring', TechnologyType.BACKEND, 10),
new ChanceTile('Chance', ChanceType.RED),
new TechnologyTile('NodeJS', TechnologyType.BACKEND, 15),
new Tile('StackOverflow', TileType.STACKOVERFLOW),
new TechnologyTile('Angular', TechnologyType.FRONTEND, 20),
new TechnologyTile('iOS', TechnologyType.MOBILE, 30),
new TechnologyTile('React', TechnologyType.FRONTEND, 25),
new ChanceTile('Chance', ChanceType.BLUE),
new ChanceTile('Chance', ChanceType.RED),
new TechnologyTile('Android', TechnologyType.MOBILE, 35),
new Tile('Go To StackOverlfow', TileType.GO_TO_STACKOVERFLOW),
new TechnologyTile('Swing', TechnologyType.NATIVE, 40),
new ChanceTile('Chance', ChanceType.BLUE),
new TechnologyTile('Qt', TechnologyType.NATIVE, 45),
new Tile('Free Debugging', TileType.DEBUGGING),
]
class Board {
constructor(tiles, root) {
this.tiles = tiles;
this.root = root;
}
render() {
this.root.innerHTML = '';
for (let i = 0; i < this.tiles.length; ++i) {
const tile = this.tiles[i].toHTML();
if (i == 0 || i == this.tiles.length - 5) {
tile.classList.add('big-square-left');
} else if ( i == 4 || i == this.tiles.length - 1) {
tile.classList.add('big-square-right');
}
if (i < 5) {
tile.classList.add('top-row');
} else if (i < this.tiles.length - 5) {
tile.classList.add(i % 2 == 0 ? 'right' : 'left');
} else {
tile.classList.add('bottom-row');
}
this.root.appendChild(tile);
}
}
}
const board = new Board(tiles, document.getElementById('root'));
board.render();
#root {
width: 80vw;
height: 80vw;
display: grid;
grid-template-rows: 2fr repeat(3, 1fr) 2fr;
grid-template-columns: repeat(7, 1fr);
}
#root > div {
border: 1px solid black;
position:relative;
}
#root div:nth-child(2n + 6) {
grid-column: 1 / span 2;
}
#root div:nth-child(2n + 7) {
grid-column: 6 / span 2;
}
#root div:nth-child(2n + 7) {
grid-column: 6 / span 2;
}
/*#root div:nth-child(n + 12) {*/
#root div.bottom-row {
grid-column: auto;
}
#root div.big-square-left {
grid-column: 1 / span 2;
}
#root div.big-square-right {
grid-column: 6 / span 2;
}
#root div p.title {
text-align: center;
position:relative;
}
#root div.top-row p.title {
transform: rotate(180deg);
top: 10%;
}
#root div.left p.title {
transform: rotate(90deg);
top: 10%;
}
#root div.left.technology p.title {
top: -85%;
}
#root div.right p.title {
transform: rotate(270deg);
}
#root div.right.technology p.title {
top: -85%;
}
#root div.right p.title {
transform: rotate(270deg);
}
#root div.big-square-right.top-row p.title {
transform: rotate(225deg);
top: 25%
}
#root div.big-square-right.bottom-row p.title {
transform: rotate(315deg);
top: 25%
}
#root div.big-square-left.bottom-row p.title {
transform: rotate(45deg);
top: 25%
}
div.colorBox {
position: relative;
}
#root > div.right > div.colorBox {
width: 20%;
height: 100%;
}
#root > div.left > div.colorBox {
width: 20%;
height: 100%;
right: -80%;
}
#root > div.top-row > div.colorBox {
height: 20%;
top: 80%;
}
#root > div.bottom-row > div.colorBox {
height: 20%;
}
svg.chance {
position: absolute;
}
#root > div.bottom-row > svg.chance
{
transform: scale(0.75);
left: -86%;
top: -5%;
}
#root > div.top-row > svg.chance
{
transform: scale(-0.75);
left: -86%;
top: -36%;
}
#root > div.left > svg.chance
{
transform: scale(0.75) rotate(90deg);
left: -36%;
top: -88%;
}
#root > div.right > svg.chance
{
transform: scale(0.75) rotate(270deg);
left: -5%;
top: -89%;
}
#root > div.chance.top-row > p.title
{
top: 68%;
}
#root > div.chance.right > p.title
{
left: -38%;
top: 10%;
}
#root > div.chance.left > p.title
{
right: -40%;
}
#root > div.chance.bottom-row > p.title
{
top: -8%;
}
<div id="root"></div>
Related
How to remove space in div class title. I want no margin width div class price
Always have space in div class title.
I try align-content: flex-start or align-items: flex-start for main_product but don't work.
If I use align-items: center for item, then..
img {
max-width: 100%;
display: block;
}
.vnt-elm {
width: 100%;
float: left;
}
.main_product {
max-width: 500px;
display: grid;
grid-gap: 10px;
}
.main_product .item {
display: grid;
grid-template-columns: 80px auto;
grid-gap: 10px;
grid-row-gap: 0;
background: #F5F5F5;
}
.main_product .item .thumb {
grid-row: 1 / 3;
}
.main_product .item .title {
background: #BA95FF;
margin: 0;
padding: 0;
}
.main_product .item .price {
background: #9CD0D8;
}
<div class="vnt-elm main_product">
<div class="vnt-elm item">
<div class="vnt-elm thumb">
<img src="https://via.placeholder.com/150" alt="">
</div>
<h4 class="vnt-elm title">The demo title of product</h4>
<div class="vnt-elm price">
<del><span class="woocommerce-Price-amount amount"><bdi>500.000<span class="woocommerce-Price-currencySymbol">U</span></bdi></span></del>
<ins><span class="woocommerce-Price-amount amount"><bdi>380.000<span class="woocommerce-Price-currencySymbol">U</span></bdi></span></ins>
</div>
</div>
<div class="vnt-elm item">
<div class="vnt-elm thumb">
<img src="https://via.placeholder.com/150" alt="">
</div>
<h4 class="vnt-elm title">The demo title of product 01</h4>
<div class="vnt-elm price">
<span class="woocommerce-Price-amount amount"><bdi>650.000<span class="woocommerce-Price-currencySymbol">U</span></bdi>
</span>
</div>
</div>
<div class="vnt-elm item">
<div class="vnt-elm thumb">
<img src="https://via.placeholder.com/150" alt="">
</div>
<h4 class="vnt-elm title">The demo title of product product product 02</h4>
<div class="vnt-elm price">
Contact US
</div>
</div>
</div>
https://codepen.io/dinhcode/pen/yLOVoGV
Any idea for case. thanks!
You might need too to set your row template :
grid-template-rows:auto 1fr ;
img {
max-width: 100%;
display: block;
}
.vnt-elm {
width: 100%;
float: left;
}
.main_product {
max-width: 500px;
display: grid;
grid-gap: 10px;
}
.main_product .item {
display: grid;
grid-template-columns: 80px auto;
grid-template-rows:auto 1fr ;
grid-gap: 10px;
grid-row-gap: 0;
background: #F5F5F5;
}
.main_product .item .thumb {
grid-row: 1 / 3;
}
.main_product .item .title {
background: #BA95FF;
margin: 0;
padding: 0;
}
.main_product .item .price {
background: #9CD0D8;
}
<div class="vnt-elm main_product">
<div class="vnt-elm item">
<div class="vnt-elm thumb">
<img src="https://via.placeholder.com/150" alt="">
</div>
<h4 class="vnt-elm title">The demo title of product</h4>
<div class="vnt-elm price">
<del><span class="woocommerce-Price-amount amount"><bdi>500.000<span class="woocommerce-Price-currencySymbol">U</span></bdi></span></del>
<ins><span class="woocommerce-Price-amount amount"><bdi>380.000<span class="woocommerce-Price-currencySymbol">U</span></bdi></span></ins>
</div>
</div>
<div class="vnt-elm item">
<div class="vnt-elm thumb">
<img src="https://via.placeholder.com/150" alt="">
</div>
<h4 class="vnt-elm title">The demo title of product 01</h4>
<div class="vnt-elm price">
<span class="woocommerce-Price-amount amount"><bdi>650.000<span class="woocommerce-Price-currencySymbol">U</span></bdi></span>
</div>
</div>
<div class="vnt-elm item">
<div class="vnt-elm thumb">
<img src="https://via.placeholder.com/150" alt="">
</div>
<h4 class="vnt-elm title">The demo title of product product product 02</h4>
<div class="vnt-elm price">
Contact US
</div>
</div>
</div>
I have total 20 images of products. I want to show these images like 1st product should be on left side and related images of that product on right hand side. Remaining products should come under 1st product column wise on the left hand side.
Currently, I am trying to do so but it is now coming properly. I am not good with CSS though. Could someone tell me what I am doing wrong?
Below is my code.
HTML
for all products images
<mat-card class="example-card" fxFlex="60%;" fxFlex.xs="80%">
<div class="grid" *ngIf="resultData">
<div class="item photo" *ngIf="anums[0]">
<img class="photothumb" [src]="resultData[0]" (click)="openImageDialogbox(resultData[0])" onError="this.src='/assets/kein-bild.gif';">
<div class="desc">
<p [routerLink]="['/rullko/produkt/', werbedata.FILIALE + werbedata.ArtNr_01]">Zum Produkt {{ anums[0] }}</p>
</div>
</div>
<div class="item photo" *ngIf="anums[1]">
<img class="photothumb" [src]="resultData[1]" (click)="openImageDialogbox(resultData[1])" onError="this.src='/assets/kein-bild.gif';">
<div class="desc">
<p [routerLink]="['/rullko/produkt/', werbedata.FILIALE + werbedata.ArtNr_02]">Zum Produkt {{ anums[1] }}</p>
</div>
</div>
<div class="item photo" *ngIf="anums[2]">
<img class="photothumb" [src]="resultData[2]" (click)="openImageDialogbox(resultData[2])" onError="this.src='/assets/kein-bild.gif';">
<div class="desc">
<p [routerLink]="['/rullko/produkt/', werbedata.FILIALE + werbedata.ArtNr_03]">Zum Produkt {{ anums[2] }}</p>
</div>
</div>
</div>
</mat-card>
For image of first product (like logo, supporting images etc)
<div class="grid">
<div class="item photo" *ngIf="secondImage">
<img class="photothumb" [src]="secondImage" onError="this.src='/assets/kein-bild.gif';">
<div class="desc">
<p>Bild 2
</div>
<div class="item photo" *ngIf="thirdImage">
<img class="photothumb" [src]="thirdImage" onError="this.src='/assets/kein-bild.gif';">
<div class="desc">
<p>Bild 3</p>
</div>
</div>
<div class="item photo" *ngIf="fourthImage">
<img class="photothumb" [src]="fourthImage" onError="this.src='/assets/kein-bild.gif';">
<div class="desc">
<p>Bild 4</p>
</div>
</div>
<div class="item photo" *ngIf="logo">
<img class="photothumb" [src]="logo" onError="this.src='/assets/kein-bild.gif';">
<div class="desc">
<p>Logo</p>
</div>
</div>
<div class="item photo" *ngIf="brandImage">
<img class="photothumb" [src]="brandImage" onError="this.src='/assets/kein-bild.gif';">
<div class="desc">
<p>Siegel</p>
</div>
</div>
</div>
</div>
CSS
.grid {
display: grid;
grid-gap: 5px;
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
grid-auto-rows: 150px;
/* flex-direction: row wrap; */
}
.item {
background-color: #ffffff;
margin: 10px;
width: 300px;
}
.photothumb {
max-width: 200px;
max-height: 200px;
cursor: pointer;
}
.desc {
padding: 10px 10px 5px 10px;
cursor: pointer;
}
.desc img {
width: 50%;
margin: 0 10px 10px 0;
float: left;
}
.desc p {
margin-bottom: 10px;
font-family: 'Arial';
font-size: 15px;
}
.photo {
grid-row-end: span 2;
}
Solution which I did :
<mat-card class="example-card" fxFlex="60%;" fxFlex.xs="80%">
<div class='some-page-wrapper'>
<div class='row'>
<div class='column'>
<div class='blue-column' *ngIf="anums[0]">
<img [src]="resultData[0]" (click)="openImageDialogbox(resultData[0])" onError="this.src='/assets/noImage.png';">
<div class="desc">
<p [routerLink]="['/rullko/produkt/', werbedata.FILIALE + werbedata.ArtNr_01]">Zum Produkt {{ anums[0] }}</p>
</div>
</div>
</div>
<div class='green-column' *ngIf="secondImage">
<img [src]="secondImage" (click)="openImageDialogbox(secondImage)" onError="this.src='/assets/noImage.png';">
<div class="desc">
<p>Bild 2</p>
</div>
</div>
</div>
</div>
</mat-card>
CSS:
.some-page-wrapper {
margin: 15px;
}
.row {
display: flex;
flex-direction: row;
flex-wrap: wrap;
width: 100%;
}
.column {
display: flex;
flex-direction: column;
flex-basis: 100%;
flex: 1;
}
I'm currently working on making a grid that will contain a different amount of items in each cells, and I am currently facing issues sizing the height of the cells in each rows accordingly :
I would like the height of each cell to be the same height as the biggest cell in each rows, but as it stands, the height of each cells depends on the highest cell in the entire grid.
Here's a mockup of what I currently have, notice how the while the cells in the third row are correct, the cells in the first and second row are too big.
.grid {
background-color: red;
display: grid;
grid-auto-columns: 1fr;
grid-auto-flow: column;
}
.grid-column {
background-color: blue;
display: grid;
grid-auto-rows: 1fr;
grid-auto-flow: row;
margin: 2px;
box-sizing: border-box;
}
.grid-row {
background-color: green;
margin: 2px;
box-sizing: border-box;
}
.item {
background-color: white;
margin: 2px;
box-sizing: border-box;
display: block;
}
<div class="grid">
<div class="grid-column">
<div class="grid-row"></div>
<div class="grid-row"></div>
<div class="grid-row"></div>
</div>
<div class="grid-column">
<div class="grid-row">
<span class="item">item 1</span>
<span class="item">item 2</span>
</div>
<div class="grid-row"></div>
<div class="grid-row"></div>
</div>
<div class="grid-column">
<div class="grid-row"></div>
<div class="grid-row">
<span class="item">item 3</span>
<span class="item">item 4</span>
</div>
<div class="grid-row"></div>
</div>
<div class="grid-column">
<div class="grid-row"></div>
<div class="grid-row"></div>
<div class="grid-row"></div>
</div>
<div class="grid-column">
<div class="grid-row"></div>
<div class="grid-row"></div>
<div class="grid-row">
<span class="item">item 5</span>
<span class="item">item 6</span>
<span class="item">item 7</span>
<span class="item">item 8</span>
</div>
</div>
</div>
I have 10 squares that are floated, and in a wrapper. I wrap each square in an anchor tag so that I can link the squares.
So I have a wrapper and inside I have 10 of these elements:
.square {
float: left;
width: calc(20% - 16px);
padding-bottom: calc(20% - 16px);
overflow: hidden;
background-image: url(myimg.jpg);
border-radius: 5%;
background-size: cover;
position: relative;
z-index: 10;
margin: 8px;
transition: ease all .3s;
color: rgb(255, 230, 20);
}
.content {
position: absolute;
width: 88%;
height: 89%;
top: 6%;
left: 6%;
cursor: pointer;
background-repeat: no-repeat;
background-size: cover;
background-position: center;
border-radius: 8px;
}
<div class="productsWrap">
<a href="mylink.com">
<div class="square">
<div class="content content1">
<span class="squareTitle">Bending</span>
</div>
</div>
</a>
//and then ten more of the same anchor tags
</div>
The first 5 squares display like stairs, and the five remaining that are in the second row display properly inline.
The problem is you are floating .square element but expecting .content to be floating. Here is the answer:
Improved HTML
<div class="productsWrap">
<div class="square">
<a href="mylink.com">
<div class="content content1">
<span class="squareTitle">Bending</span>
</div>
</a>
</div>
<div class="square">
<a href="mylink.com">
<div class="content content1">
<span class="squareTitle">Bending</span>
</div>
</a>
</div>
<div class="square">
<a href="mylink.com">
<div class="content content1">
<span class="squareTitle">Bending</span>
</div>
</a>
</div>
<div class="square">
<a href="mylink.com">
<div class="content content1">
<span class="squareTitle">Bending</span>
</div>
</a>
</div>
<div class="square">
<a href="mylink.com">
<div class="content content1">
<span class="squareTitle">Bending</span>
</div>
</a>
</div>
<div class="square">
<a href="mylink.com">
<div class="content content1">
<span class="squareTitle">Bending</span>
</div>
</a>
</div>
<div class="square">
<a href="mylink.com">
<div class="content content1">
<span class="squareTitle">Bending</span>
</div>
</a>
</div>
<div class="square">
<a href="mylink.com">
<div class="content content1">
<span class="squareTitle">Bending</span>
</div>
</a>
</div>
<div class="square">
<a href="mylink.com">
<div class="content content1">
<span class="squareTitle">Bending</span>
</div>
</a>
</div>
<div class="square">
<a href="mylink.com">
<div class="content content1">
<span class="squareTitle">Bending</span>
</div>
</a>
</div>
</div>
Improved CSS
.square {
float: left;
width: calc(20% - 16px);
padding-bottom: calc(20% - 16px);
overflow: hidden;
background: #f00;
border-radius: 5%;
background-size: cover;
position: relative;
z-index: 10;
margin: 8px;
transition: ease all .3s;
color: rgb(255, 230, 20);
}
.square a {
color:yellow;
}
.content {
position: absolute;
width: 88%;
height: 89%;
top: 6%;
left: 6%;
cursor: pointer;
background-repeat: no-repeat;
background-size: cover;
background-position: center;
border-radius: 8px;
}
And Here is the result
enter image description here
I want to have a structure like this:
But its not working, the image, date, title and subtitle are ok, but then do you know how to put the Image title right below the image and the view and save links below the other texts with the same margin-left of 1rem?
I have here the Example: http://jsfiddle.net/tyyj57gs/6/, the issue should be because the horizontal-card div have display flex but Im not having sucess solving that issue.
Html:
<div class="container pb-4">
<div class="row">
<div class="col-lg-3">
<div class="horizontal-card">
<img src="http://via.placeholder.com/200x100"/>
<div class="horizontal-card-body">
<span class="card-text">Date</span>
<h4 class="card-title">Title</h4>
<span class="card-text">Subtitle</span>
</div>
<div class="horizontal-card-footer">
<span>Image Title</span>
<a class="card-text status">#View</a>
<a class="card-text status">#Save</a>
</div>
</div>
</div>
CSS
.horizontal-card{
display: flex;
border:1px solid gray;
margin-bottom:1rem;
img{
width: 200px;
height: 100px;
border-bottom: 2px solid red;
}
.horizontal-card-body{
display: flex;
flex-direction: column;
margin-left:1rem;
}
}
I did this by using display:inline-block instead of the flex box you had. The sections are broken into two rows. Add style as you wish.
HTML:
<div class="card">
<div class="row">
<div class="innerLeft">
<img src="http://via.placeholder.com/200x100"/>
</div>
<div class="innerRight">
<div class="horizontal-card-footer">
<span class="card-text">Date</span>
<h4 class="card-title">Title</h4>
<span class="card-text">Subtitle</span>
</div>
</div>
</div>
<div class="row">
<div class="innerLeft">
<p>Image Title</p>
</div>
<div class="innerRight">
<a class="card-text status">#View</a>
<a class="card-text status">#Save</a>
</div>
</div>
</div>
CSS:
.card {
display:block;
width:100%;
max-width:800px;
}
img {
width: 100%;
height: auto;
border-bottom: 2px solid orange;
}
.innerLeft {
display:inline-block;
margin-right:-4px;
vertical-align:top;
width:30%;
text-align:center;
padding:5px;
}
.innerRight {
display:inline-block;
vertical-align:top;
width:70%;
text-align:left;
padding:5px;
}
.card-text {
display:inline-block;
}
FIDDLE : http://jsfiddle.net/tyyj57gs/9/
You can create the layout you want using flexbox.
In the snippet below I have restructured your .horizontal-card into .card-left and .card-right.
.horizontal-card {
display: flex;
border: 1px solid gray;
margin-bottom: 1rem;
}
.card-left,
.card-right {
display: flex;
flex-direction: column;
}
.card-right {
width: 100%;
}
.card-left span {
background: orange;
flex: 1;
display: flex;
justify-content: center;
align-items: center;
}
.horizontal-card-body,
.horizontal-card-footer {
padding-left: 1em;
}
img {
width: 200px;
height: 100px;
}
.horizontal-card-footer {
/* Add to ensure the footer is pinned to the bottom of the card */
margin-top: auto;
border-top: 1px solid grey;
}
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css" rel="stylesheet">
<div class="container pb-4">
<div class="row">
<div class="col-lg-3">
<div class="horizontal-card">
<div class="card-left">
<img src="http://via.placeholder.com/200x100" />
<span>Image Title</span>
</div>
<div class="card-right">
<div class="horizontal-card-body">
<span class="card-text">Date</span>
<h4 class="card-title">Title</h4>
<span class="card-text">Subtitle</span>
</div>
<div class="horizontal-card-footer">
<a class="card-text status">#View</a>
<a class="card-text status">#Save</a>
</div>
</div>
</div>
</div>
<div class="container pb-4">
<div class="row">
<div class="col-lg-3">
<div class="horizontal-card">
<div class="card-left">
<img src="http://via.placeholder.com/200x100" />
<span>Image Title</span>
</div>
<div class="card-right">
<div class="horizontal-card-body">
<span class="card-text">Date</span>
<h4 class="card-title">Title</h4>
<span class="card-text">I am a card with a longer subtitle. I am a card with a longer subtitle. I am a card with a longer subtitle. I am a card with a longer subtitle. </span>
</div>
<div class="horizontal-card-footer">
<a class="card-text status">#View</a>
<a class="card-text status">#Save</a>
</div>
</div>
</div>
</div>
<div class="container pb-4">
<div class="row">
<div class="col-lg-3">
<div class="horizontal-card">
<div class="card-left">
<img src="http://via.placeholder.com/200x100" />
<span>Image Title</span>
</div>
<div class="card-right">
<div class="horizontal-card-body">
<span class="card-text">Date</span>
<h4 class="card-title">Title</h4>
<span class="card-text"></span>
</div>
<div class="horizontal-card-footer">
<a class="card-text status">#View</a>
<a class="card-text status">#Save</a>
</div>
</div>
</div>
</div>
Here is my version of the image. Let me know if there are any issues, I have used position absolute for the footer's position.
For the SCSS version of the CSS refer the fiddle, else refer the snippet below!
JSFiddle Demo
.horizontal-card {
position: relative;
display: flex;
border: 1px solid gray;
margin-bottom: 1rem;
}
.horizontal-card img {
width: 200px;
height: 130px;
border-bottom: 30px solid orange;
}
.horizontal-card .horizontal-card-body {
display: flex;
flex-direction: column;
margin-left: 1rem;
}
.horizontal-card .horizontal-card-footer {
position: absolute;
left: 0px;
right: 0px;
bottom: 0px;
height: 30px;
display: flex;
align-items: center;
}
.horizontal-card .horizontal-card-footer span {
width: 200px;
display: inline-block;
}
.horizontal-card .horizontal-card-footer a {
margin-left: 10px;
}
<div class="container pb-4">
<div class="row">
<div class="col-lg-3">
<div class="horizontal-card">
<img src="http://via.placeholder.com/200x100" />
<div class="horizontal-card-body">
<span class="card-text">Date</span>
<h4 class="card-title">Title</h4>
<span class="card-text">Subtitle</span>
</div>
<div class="horizontal-card-footer">
<span>Image Title</span>
<a class="card-text status">#View</a>
<a class="card-text status">#Save</a>
</div>
</div>
</div>