tutos

Code an avatar card

Saturday 13th January, 2018 —

Get started

Hello everyone, today we are going to talk about css positioning. When i was still a beginner learning css i struggled when i had to use css position properties. Css positioning is a topic that needs much more than a single blog post to master. That's why this post will be the first of a series on css positioning.

What we are going to do

We are going to build a user card UI element with an image avatar. We will position the avatar absolutely to give the card a unique feel. I made a pen at codepen.io for this post. It shows the card that we are going to build together. You can find the pen here.

See the Pen Card avatar position by Driss Chelouati (@cssninjaStudio) on CodePen.

Setting up

To do this tutorial, i recommend that you create a new pen on codepen or any html playground you're used to. Once you have your new pen (i assume that you use codepen like me), you are ready to get started with this tutorial. You will need however to do two things before we start :

  • Click on one of the the cog wheels of the code editor section to configure your project settings.
  • In the CSS tab, click on the CSS preprocessor select and choose SCSS
  • In the same tab, add bulma css framework as an external library using a cdn, just paste the following inside one of the ressource fields :

https://cdnjs.cloudflare.com/ajax/libs/bulma/0.6.2/css/bulma.css

  • You are now ready to start this tutorial. Let's go !

Set up a layout

before we even start thinking how our card is going to look, we need a layout for the page that is going to display it. No fancy things, we will go straight to the point. Let's begin with some markup using the Bulma grid to speed up our layout setup. We are going to start with a section, a container, columns (equivalent to bootstrap rows) and column (wich is the same than Bootstrap columns).

<div class="section">
  <div class="container">
    <div class="columns">
      <div class="column is-4 is-offset-4"></div>
    </div>
  </div>
</div>

Bulma uses a 12 column grid system, like Bootstrap. To center our user card horizontally on the screen, we are dividing the grid in 3 equal sections. We are pushing a 4 column (wich represents one third of the layout) and offsettting it by 4. That means that we let a 4 column space before and after our main column. Now that our column is centered, we will need to add basic styles. let's set the body height and width to 100% and it's position to relative.

body {
  position: relative;
  height: 100%;
  width: 100%;
}

.columns {
  margin-top: 80px;
}

We chose to use SCSS as our preprocessor, so we will add some color variables to work with :

$primary: #7f00ff;
$secondary: #00d1b2;
$section: #ededed;
$muted: #999;

Card markup

It is time to add the markup for our card. We will use a predefined bulma class wich is .card as a base for our own UI element. Here are the styles that Bulma holds for the .card class. We will start from this and build our own card.

.card {
  background-color: white;
  box-shadow: rgba(10, 10, 10, 0.1) 0px 2px 3px, rgba(10, 10, 10, 0.1) 0px 0px 0px
      1px;
  color: rgb(74, 74, 74);
  max-width: 100%;
}

We will need several things in our card. We will need a header, that will hold the avatar. We also need some user info and an action, like a button. Let's start by writing the card markup inside our .card div element. Let's start with the header :

<div class="header">
  <div class="avatar">
    <img src="https://image.ibb.co/fa2YRF/dounia.jpg" alt="" />
  </div>
</div>

Let's write the rest of the markup before we dive into the css styles. After the header, we need to add the .card-body section and the .action section. After the header div insert the card body element. The card body will hold the user-meta (name, position and description) and the action will hold a button.

<div class="card-body">
  <div class="user-meta has-text-centered">
    <h3 class="username">Helen Miller</h3>
    <h5 class="position">Accountant</h5>
  </div>
  <div class="user-bio has-text-centered">
    <p>
      Helen Miller is an accountant at the Acme Inc comany. She works very hard.
    </p>
  </div>
  <div class="action has-text-centered">
    <a href="#" class="button is-small">View profile</a>
  </div>
</div>

We've finished writing the markup. You should now have something that looks like this :

<div class="section">
  <div class="container">
    <div class="columns">
      <div class="column is-4 is-offset-4">
        <div class="card">
          <div class="header">
            <div class="avatar">
              <img src="https://image.ibb.co/fa2YRF/dounia.jpg" alt="" />
            </div>
          </div>
          <div class="card-body">
            <div class="user-meta has-text-centered">
              <h3 class="username">Helen Miller</h3>
              <h5 class="position">Accountant</h5>
            </div>
            <div class="user-bio has-text-centered">
              <p>
                Helen Miller is an accountant at the Acme Inc comany. She works
                very hard.
              </p>
            </div>
            <div class="action has-text-centered">
              <a href="#" class="button is-small">View profile</a>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</div>

We are now ready to apply our styles to make this card look gorgeous !

Adding card styles

Now that our markup is ready, we can apply our styles.

Section styles

We need to add some styles to our section element, to emphasize the card we are building. we will define a height and a background color for more consistency. Don't forget that SCSS supports nesting and indentation. We will use this feature to style our card. All styles will be nested inside the section styles.

.section {
  background-color: $section;
  min-height: 100vh;
  position: relative;
}

Card styles

Our card is shipped from bulma with basic styles. We only need to define some border-radius and the overflow properties. The border radius adds a nice rounded effect to the card whereas the overflow property prevents some unexpected behaviours, but its more of habit and remains optionnal.

.card {
  border-radius: 6px;
  overflow: hidden;
}

Header styles

This is the visual focus point of the card because it holds the user avatar. To achieve a nice visual effect, styles have to be polished. This is also were we are going to do some absolute positioning. Let's add the styles and break them one by one :

.header {
  height: 120px;
  background: $primary;
  .avatar {
    width: 80px;
    height: 100%;
    position: relative;
    margin: 0 auto;
    img {
      display: block;
      border-radius: 50%;
      position: absolute;
      bottom: -42px;
      border: 4px solid $white;
    }
  }
}

What happens here? First of all we are giving a size to the header and a background color. We will then style the .avatar div that acts as a container for our avatar image. We are giving it a width of 80px so our image doesn't actually ecxeed these dimensions (notice that for avatars, you should use images with a square ratio). We are also setting its position to relative because our child img element is going to be poisitioned absolutely. Why is that ? Because absolutely positioned elements position themselves relatively to their first encountered parent (when climbing back the DOM tree) with position: relative; . To stay simple, this is how absolute positioning works.

We are also setting the .avatar margin property to margin: 0 auto; . This is needed to center horizontaly our avatar element. Although we gave it a 80px width, we set its height to 100% because we want it to have the same height as the .header parent element. Why do we want that? Because we want to create a relative space were we can play with our child image element's position.

Let's see the img element styles. We first need to change the default display: inline; property that all img elements have. We change it to display: block; so our image behaves as expected. If you want to, you can learn more about the display property at W3C. Then we add what i like to call "cosmetic styles" like the border-radius and the border properties to give our avatar image a more consistent look.

The only thing left is to position our image. We will use absolute positioning for that. The first relative parent is the .avatar div, wich has the same height than the .header element. We will only use the bottom property because our image is already centered. We want our image to sit at the bottom part of the header. So let's start by setting the bottom property to 0. You will see that the bottom edge of your image is aligned with the bottom border of the header. But if you look at our Pen, we can actually see that we want our image to be cut in half by the header bottom border. This is really easy to achieve.

Remember? Our .avatar div has a 80px width and our image has a square ratio. By this we know that our image dimensions are 80x80 pixels. We also know that it has a border of 4px width. We know all we need to finish positioning our image. To make it look like it is divided by the header and the card body intersection, we are going to offset it by the half of it's height (40px) plus the half of its border width (2px):

position: absolute;
bottom: -42px;

That's it ! we have a nice looking card avatar !

Finishing styling

We then add our card body and button styles to finish our card :

.card-body {
  padding: 30px;
  .user-meta {
    padding-top: 20px;
    .username {
      font-size: 18px;
      font-weight: 600;
    }
    .position {
      font-size: 90%;
      color: $primary;
    }
  }
}
.user-bio {
  padding-top: 8px;
  font-size: 92%;
  color: $muted;
}
.action {
  padding-top: 20px;
  .button {
    padding: 16px 20px 16px 20px;
    background: $primary;
    border-color: $primary;
    color: $white;
    border-radius: 100px;
    transition: opacity 0.3s;
    &:hover {
      opacity: 0.7;
    }
  }
}

Epilogue

In this post, we saw how to use absolute positioning to emphasize a UI element and to give it a nice and trendy design. Of course there are many other ways to achieve the same effects. If you want to share your thoughts or ask a question, give it a shot in the comments section. I hope you enjoyed this little session as much as i did writing it and to see you again soon on Css Ninja.

Back to Blog

Continue reading

Server Cache Invalidation in Nuxt and Nitro

Top 10 Vue Components Libraries

How to build a filterable list with Nuxt and Tailwind