Niko
Niko

Reputation: 361

How to create a completely flexible piano keyboard with HTML and CSS

I'm trying to create a piano keyboard that will keep its elements ratios using flex box, but can't seem to make the black notes stay the same width or height once I start changing the window size.

Here is a fiddle

body{
width: 800px;
height: 200px;
display: flex;
}

#kbd {

padding: 1%;
flex-flow: column;
display: flex;
flex: 4;
}

#keys {
display: flex;
flex: 8;
justify-content: center;
}


.note {
flex: 1;
display: inline-flex;
align-items: center;
}

.black {
justify-content: center;
position: absolute;
height: 45%;
background-color: #474747;
color: white;
width: 8%;
margin: 0 -4%; 
}

.white {
flex-flow: column;
justify-content: flex-end;
outline: 2px solid #474747;
color: #474747;
background-color: #ffffff;
padding-bottom: 1%;
}

Upvotes: 2

Views: 5773

Answers (4)

Enteleform
Enteleform

Reputation: 3843

Demo @ Codepen


Flexbox is not required for this. A responsive keyboard layout can be accomplished with:
 

  • additional class selectors that correspond with the note of each key:
<div class="key white c"      ></div>
<div class="key black c_sharp"></div>
<div class="key white d"      ></div>
<div class="key black d_sharp"></div>
<div class="key white e"      ></div>
<div class="key white f"      ></div>
<div class="key black f_sharp"></div>
<div class="key white g"      ></div>
<div class="key black g_sharp"></div>
<div class="key white a"      ></div>
<div class="key black a_sharp"></div>
<div class="key white b"      ></div>

 

  • a margin for all black keys & each white key which precedes a black key, using an offset based on the black key's size:
.a, .b, .d, .e, .g, .black{
  margin: 0 0 0 (-($blackKey_Width / 2) - $blackKey_BorderWidth);
}

 

  • the following key placement attributes:
.key{
  float:    left;
  position: relative;
}

 

  • a higher z-index for the black keys:
.white{
  z-index: 1;
}
.black{
  z-index: 2;
}

 

  • Viewport Units [vw, vh, vmin, vmax] for the (height & width) attributes of the (.white & .black) selectors. You can make this even more dynamic by sizing the black keys as a percentage of the white keys.

Upvotes: 5

tony
tony

Reputation: 945

Not sure if you need your black keys to be independent blocks but here is an example

<body>
   <div class="note-container">
     <div class="white-note black-note"></div> 
     <div class="white-note black-note"></div>
     <div class="white-note"></div> 
     <div class="white-note black-note"></div>
     <div class="white-note black-note"></div> 
     <div class="white-note black-note"></div>
     <div class="white-note"></div> 
     <div class="white-note black-note"></div>
     <div class="white-note black-note"></div> 
     <div class="white-note"></div>
   </div>  
</body>

body {
  background: #000;
}

.note-container {
  width: 100%;
  display: flex;
  flex-flow: row nowrap;
}

.white-note {
  position: relative;
  width: 10%;
  height: 400px;
  background: #fff;
  margin: 0 2px;
}

.white-note.black-note:after {
  content: "";
  position: absolute;
  top: 0;
  right: -25%;
  width: 50%;
  height: 50%;
  background: #000;
  z-index: 1;
}

Upvotes: 1

logicalcoder
logicalcoder

Reputation: 152

The position should be relative rather than absolute. Also you should set both the height of the containing divs to 100%.

Refer to the Fiddle link: http://jsfiddle.net/924sefae/6/

#kbd {
  height: 100%;
  ...
}
#kbd {
  height: 100%;
  ...
}

.black {
  position: relative;
  ...
}

Upvotes: 2

Wouter Florijn
Wouter Florijn

Reputation: 2951

Percentage height is calculated based on the height of the first positioned parent. In this case, the #keys and #kbd divs don't have a position CSS rule. This means the black keys are scaled based on the width of the body, instead of their direct parent.

Add position: relative; to the #keys div to make it work properly.

Upvotes: 3

Related Questions