My goal of this tutorial is to keep things as plain as possible so that it might be easier for beginning developers, and developers who may not have worked with my specific stack, to dig into quickly. Of course, feel free to use whatever technology, colors, fonts, etc. you like! That being said, let's get started.


What's Needed

Here I've included an outline of the types of code needed for this tutorial, from basic HTML elements to CSS properties to styling choices like colors and fonts.

  • HTML
    • Block-level elements, such as <div> and <header>
    • Paragraph element <p>
    • Span elemenent <span>
  • CSS
    • position: relative, along with top, right, bottom, & left.
    • linear-gradient & repeating-linear-gradient
    • line-spacing
  • Other
    • Colors: Light Blue #9198E5, Pink (I just used the keyword pink), White (again, I used the keyword white)
    • Fonts: cursive for a handwritten feel or monospace for a typewriter feel.

HTML & Some Basic CSS

The basic structure is two block-level elements, each with its own background linear-gradient and text.


There's two ways to do this - you can either place the two block elements next to each other as sibling elements, or you can nest one inside the other. I've chosen to nest one inside the other.

  <div class="card">
  <span class="card-title">A Title</span>
 <p class="card-text">Some body text</p>

Here, the <div> defines the whole area of the paper, and the <header> defines the top margin.


I wanted to roughly match the dimensions of a typical index card. I chose to go with 3"x5" (about 7.5cm x 12.5cm), which I converted into pixels by multiplying by 100; 300px high and 500px wide. The header area of an index card isn't very big, so I went with 36px for that. It was all very scientific. The width of the <header> should be 100%, but as a block-level element, it will do this by default. So now our CSS should look like this:

  .card {
 width: 500px;
 height: 300px;
header {
 height: 36px;

The Backgrounds

Okay, now we have a couple of elements that are positioned and sized properly, but they have no background. Let's fix that.

For the <header>, I used linear-gradient() with white and pink, utilizing the color stops feature to manipulate the gradient into defined lines.

Side Note: For the header, you could absolutely specify something like { border-bottom: 2px solid pink } instead of using a gradient. However, I chose to use the gradient because it allowed me to create an effect similar to ink bleed.

  header {
 height: 36px;
 background: linear-gradient(
  white, white 33px,
  pink 35px, pink 36px);

This code starts white at 0px (unspecified) and ends it at 33px. It then starts pink at 35px and ends it at 36px, which matches the height of my header. Between the two colors, there's a gap of 2px, which produces a slight white-to-pink gradient. This is my ink bleed effect.

Next, the background for .card should have a bunch of horizontal blue lines. border-bottom won't work here like it would on the header, and while you could write linear-gradient() to specify each line, that's a huge, frustrating waste of time! Instead, we'll use repeating-linear-gradient(), which works the same way but allows us to specify one section and then the CSS figures out the rest for us. Here's what mine looks like:

  .card {
 background: repeating-linear-gradient(
  white, white 25px,
  #9198e5 26px, #9198e5 27px

This should look familiar, as it's almost exactly the same as what I used for <header>'s pink line. Note, however, that the white area isn't as high, and that the blue line has less bleed effect and therefore appears thinner (1px each instead of 2px bleed and 1px line). The white areas in the lined area are supposed to be shorter, and the lines less bold.

Caution! A problem I encountered here was getting my first blue line to start an appropriate distance away from the pink line. My solution at the time was to play around with the spacing on my blue lines until I found something that looked good, but as I was writing this I suddenly remembered that background-position exists. So if you like the spacing on your blue lines, but the white gap between your pink and first blue line doesn't look good, you can use background-position-y to set it to start after your header area (set it to the height of the header). Time to take a short break and revise my code!

Adding Text

When I first came up with the idea to create an index card display for text, adding the text is the part that both excited and scared me. I was excited because, if I could get it right, it would look so cool! But I was scared of it because I wasn't sure how to make it work. I'm certain there are other ways of doing it, but here's what I did; turns out it's pretty easy.

  1. Added position: relative to .card-title and .card-text. These are the two items that will contain text, and we use the positioning to place them on the lines.
  2. On .card-title I also set top: 5px and left: 10px. The left property could be replaced with a margin or padding property; using positioning isn't important. However, setting top to 5 pixels moves it down enough to sit right on that pink line without changing how the card looks.
  3. On .card-text I had to add quite a few properties, so here's the whole block:
  .card-text {
 position: relative;
 top: 30px;
 font-size: 18px;
 margin: 0 20px;
 line-height: 27px;

The real key to making all of this work is line-height: set it to match the height of your repeating gradient (for me, it was 27px), and the lines of text will have the same spacing as your blue lines do. In addition, you may need to play around with the value for top: I set it to 30px so my text would start on the second blue line. If you want it to start on the first blue line you'll have to set it to 3px, and if you changed the spacing entirely you'll have to tweak it until it's right.

You'll probably want your font-size to be smaller than the white area on your gradient, but not too much smaller or it might look strange.

The margin here could also be accomplished with padding, but keep in mind that <p> has a top-margin by default, which will change your top value.

BONUS: Adding Margins

I've also included an example of how a loose-leaf sheet (lined paper with margins and punched holes) might be created, and I have here a few notes on the changes that I made.

  • Sizes everywhere were changed, because the ratio of the paper is different and the size of the header is different.
  • The structure of the HTML changes a little bit to include two more <div> elements for the margins.
    • I put these before the header in my structure.
    • On this type of paper, the margins are designated by pink lines, so I added a pink border to the inner edge of each <div>.
    • float: left and float: right allow them to sit next to the <header> and <p> without conflicting, but also mean I had to adjust the padding/margin property of .sheet-title and .sheet-text to account for that.
    • I also had to specify a width for .sheet-text so that it wouldn't interfere with my right margin.
  • The first line on a sheet of this paper is usually blue rather than pink, so I changed the color used for <header>'s background gradient.
  • Within the left margin <div> I included three more, which represent punched holes.
    • background-color: #555 matches my body background
    • height: 20px; width: 20px; border-radius: 50% makes them 20px circles.
    • Each hole has position: absolute and .l-margin got position: relative added so that I could position each of them properly.

Working Example

Edited August 20, 2019

@Oznog commented to point out a mistake I made, where I used IDs instead of classes. The edits to the post and example pen include:

  • Changed #card to .card (id to class)
  • Changed #title to .card-title and .sheet-title; also changed #text to .card-text and .sheet-text (generic id to specific class)

Anyone who wants to make something similar is, of course, free to use IDs or Classes as fits their needs.

Thanks for pointing it out!