Reputation: 2712
I am trying to create guitar tabulature with html/css.
I have this basic layout you can see here
Style
* {
margin:0;
padding:0;
box-sizing: border-box;
font-family:sans-serif;
}
.wrapper {
height:100px;
width:600px;
margin: 70px auto;
display:flex;
flex-direction:column;
justify-content:space-between;
}
.string {
height:1px;
width:100%;
background:black;
}
Html
<div class="wrapper">
<div class="string"></div>
<div class="string"></div>
<div class="string"></div>
<div class="string"></div>
<div class="string"></div>
<div class="string"></div>
</div>
<div class="wrapper">
<div class="string"></div>
<div class="string"></div>
<div class="string"></div>
<div class="string"></div>
<div class="string"></div>
<div class="string"></div>
</div>
I would like to be able to place notes (numbers) on the strings like
------0-
-----0--
----0---
---2----
--2-----
-0------
also chords like
-0------
-0------
-0------
-2------
-2------
-0------
What would be the easiest way to achieve this?
Upvotes: 5
Views: 883
Reputation: 2452
Although the correct answer has already been given, you could try another solution, that in my opinion, could be more scalable. Using CSS variables and CSS grid, basically.
:root {
--noteA: 20%;
--noteB: 40%;
--noteC: 60%;
--noteD: 80%;
--order: '';
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: sans-serif;
}
body {
display: flex;
justify-content: center;
align-items: center;
}
.wrapper {
display: grid;
grid-template-rows: repeat(6, 30px);
grid-template-columns: repeat(6, 100px);
grid-auto-flow: column;
align-items: center;
grid-gap: 5px;
}
.string {
height: 50%;
background-color: #8000805e;
grid-column: span 6;
}
.note-a:after {
content: var(--order);
position: relative;
left: var(--noteA);
}
.note-b:after {
content: var(--order);
position: relative;
left: var(--noteB);
}
.note-c:after {
content: var(--order);
position: relative;
left: var(--noteC);
}
.note-d:after {
content: var(--order);
position: relative;
left: var(--noteD);
}
<div class="wrapper">
<div class="string note-a" style="--order:'1'"></div>
<div class="string note-b" style="--order:'2'"></div>
<div class="string note-a" style="--order:'3'"></div>
<div class="string note-c" style="--order:'4'"></div>
<div class="string note-d" style="--order:'5'"></div>
<div class="string note-c" style="--order:'6'"></div>
</div>
You can also take a look at this pen.
Upvotes: 0
Reputation: 273011
I would do this with less of code relying on transformation to adjust the position. Simply pay attention to the different value to have a perfect alignment:
.wrapper {
margin-top:30px;
height: 96px; /* (16px)*6 */
background:
repeating-linear-gradient(
to bottom,
transparent 0 calc(100%/6 - 1px),#000 calc(100%/6 - 1px) calc(100%/6))
0 -8px; /* (16px)/2 */
position:relative;
}
.note {
position:absolute;
font-family:sans-serif;
top:0;
left:0;
padding:0 4px; /*4px will control distance between notes*/
line-height:16px; /* Line-height not height!*/
width:10px;
background: #fff;
transform:translate(calc(var(--x,0)*100%),calc(var(--y,0)*100%));
}
<div class="wrapper">
<span class="note">5</span>
<span class="note" style="--x:0;--y:2">3</span>
<span class="note" style="--x:1;--y:5">8</span>
<span class="note" style="--x:2;--y:4">9</span>
<span class="note" style="--x:3;--y:3">1</span>
<span class="note" style="--x:4;--y:2">9</span>
<span class="note" style="--x:5;--y:1">7</span>
<span class="note" style="--x:7;--y:5">7</span>
<span class="note" style="--x:2;--y:0">2</span>
</div>
You can make it more responsive using em
unit:
.wrapper {
margin-top:30px;
height: 6em;
background:
repeating-linear-gradient(
to bottom,
transparent 0 calc(100%/6 - 1px),#000 calc(100%/6 - 1px) calc(100%/6))
0 -0.5em;
position:relative;
}
.note {
position:absolute;
font-family:sans-serif;
top:0;
left:0;
padding:0 0.2em;
line-height:1em;
width:0.5em;
background: #fff;
transform:translate(calc(var(--x,0)*100%),calc(var(--y,0)*100%));
}
<div class="wrapper">
<span class="note">5</span>
<span class="note" style="--x:0;--y:2">3</span>
<span class="note" style="--x:1;--y:5">8</span>
<span class="note" style="--x:2;--y:4">9</span>
<span class="note" style="--x:3;--y:3">1</span>
<span class="note" style="--x:4;--y:2">9</span>
<span class="note" style="--x:5;--y:1">7</span>
<span class="note" style="--x:7;--y:5">7</span>
<span class="note" style="--x:2;--y:0">2</span>
</div>
<div class="wrapper" style="font-size:30px">
<span class="note">5</span>
<span class="note" style="--x:0;--y:2">3</span>
<span class="note" style="--x:1;--y:5">8</span>
<span class="note" style="--x:2;--y:4">9</span>
<span class="note" style="--x:3;--y:3">1</span>
<span class="note" style="--x:4;--y:2">9</span>
<span class="note" style="--x:5;--y:1">7</span>
<span class="note" style="--x:7;--y:5">7</span>
<span class="note" style="--x:2;--y:0">2</span>
</div>
In case you need better support for old browser you can get rid of calc()
and CSS variables:
.wrapper {
margin-top:30px;
height: 6em;
background:
repeating-linear-gradient(
to bottom,
transparent 0 0.95em,#000 0.95em 1em)
0 -0.5em;
position:relative;
}
.note {
position:absolute;
font-family:sans-serif;
top:0;
left:0;
padding:0 0.2em;
line-height:1em;
width:0.5em;
background: #fff;
}
<div class="wrapper">
<span class="note">5</span>
<span class="note" style="transform:translate(0,200%)">3</span>
<span class="note" style="transform:translate(100%,500%)">8</span>
<span class="note" style="transform:translate(200%,400%)">9</span>
<span class="note" style="transform:translate(300%,300%)">1</span>
<span class="note" style="transform:translate(400%,200%)">9</span>
<span class="note" style="transform:translate(500%,100%)">7</span>
<span class="note" style="transform:translate(700%,500%)">7</span>
<span class="note" style="transform:translate(200%,0)">2</span>
</div>
Upvotes: 4
Reputation: 61083
You can do it with markup (spacer notes), or you could create CSS rules to indicate position along each line.
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: sans-serif;
}
.wrapper {
height: 100px;
max-width: 700px;
margin: 30px auto 40px auto;
display: flex;
flex-direction: column;
justify-content: space-between;
}
.string {
height: 1px;
width: 100%;
background: black;
}
.note,
.spacer {
display: inline-block;
width: 12px;
height: 12px;
line-height: 12px;
background: #fff;
text-align: center;
transform: translateY(-8px);
margin-left: 15px;
}
.spacer {
opacity: 0;
}
<div class="wrapper">
<div class="string">
<div class="spacer"></div>
<div class="spacer"></div>
<div class="spacer"></div>
<div class="spacer"></div>
<div class="spacer"></div>
<div class="note">3</div>
</div>
<div class="string">
<div class="spacer"></div>
<div class="spacer"></div>
<div class="spacer"></div>
<div class="spacer"></div>
<div class="note">4</div>
</div>
<div class="string">
<class="string">
<div class="spacer"></div>
<div class="spacer"></div>
<div class="spacer"></div>
<div class="note">2</div>
</div>
<div class="string">
<div class="spacer"></div>
<div class="spacer"></div>
<div class="note">1</div>
</div>
<div class="string">
<div class="spacer"></div>
<div class="note">2</div>
</div>
<div class="string">
<div class="note">1</div>
</div>
</div>
Yes, I do have seven fingers on each hand.
Upvotes: 4