Profile Picture Lab

Your face is your first handshake

A great profile picture earns trust in under a second. Learn what makes a photo look professional, what sinks it, and why the smallest smile makes the biggest difference.

Step 1

Why your profile picture actually matters

On LinkedIn, Slack, your résumé, and Zoom — your headshot is often the first (and sometimes only) thing a recruiter, teacher, or client sees before deciding whether to read the rest.

First impressions are instant

People form an opinion of your face in roughly 1/10th of a second — before they read a word.

Trust is visual

A clear, friendly photo makes you feel 40% more trustworthy than a blurry or missing one.

Recruiters judge fast

On LinkedIn, profiles with a photo get 21× more views and 9× more connection requests.

It's your brand

The same face across LinkedIn, GitHub, email, and your portfolio makes you instantly recognizable.

Step 2

Professional vs. unprofessional — the rules

The difference usually isn't about expensive cameras or makeup — it's about the basics below. Aim for all the "do's" and skip every "don't".

Do

  • Face the camera, shoulders slightly turned
  • Use soft, even light (a window at noon is free and perfect)
  • Frame head + top of shoulders — not a full body shot
  • Plain or softly blurred background
  • Wear what you'd wear to the job you want
  • Smile with your eyes (more on this below)
  • Crop square — most platforms display a circle
  • Make sure your face fills about 60% of the frame

Don't

  • Crop out someone else — visible hands or arms give it away
  • Use a selfie with a bathroom mirror or flash
  • Sunglasses, hats, or anything hiding your eyes
  • Party photos, vacation shots, beach shots
  • Heavy filters, blurry shots, or pixelated uploads
  • Distracting backgrounds (messy room, busy signs)
  • Photos that are 5+ years old
  • Pet or cartoon avatars for professional profiles
Step 3

Spot the difference

These illustrated examples show what platforms actually see. Scan the tags — green for professional, yellow for "maybe for casual use", red for "replace immediately."

Professional

Clean background, centered face, genuine smile, good lighting.

Professional

Simple neutral backdrop, head-and-shoulders crop, approachable expression.

Don't

Cluttered, chaotic background pulls attention away from your face.

Don't

Sunglasses hide your eyes — the most important part of connecting with a viewer.

Don't

Party or nightlife photos signal the wrong context for work or school.

Only if casual

A fun avatar works on Discord or a personal blog, but not on a résumé.

Step 4

Why smiling is the #1 rule

A smile is the fastest shortcut to "likeable."

Our brains read faces constantly. A relaxed, closed-mouth smile (or a warm teeth-showing one) signals confidence, warmth, and openness — the exact qualities people are looking for in coworkers, classmates, and clients.

+45%
more likely to be perceived as competent when smiling
+36%
higher rating for likeability vs. a neutral face
+14×
LinkedIn profile views with a smiling photo
0.1s
how long it takes someone to judge your face

How to smile without looking weird

A forced smile is worse than no smile. Try these tricks photographers actually use:

Smize — smile with your eyes

Think of something genuinely funny right before the shutter clicks. Your eyes will crinkle slightly — that's what makes a smile look real.

Start big, relax into it

Laugh out loud, then let the smile settle naturally. The "post-laugh" face is photogenic gold.

Take 20+ photos

Even models don't nail it first try. Burst mode + picking the best frame is a pro secret.

Closed-mouth also works

If showing teeth feels forced, a slight upward curl with relaxed eyes reads as confident and warm.

Step 5

Try it — mock up your profile card

Pick initials, a color, and an expression. See how it looks cropped into a circle the way LinkedIn, Slack, and GitHub will display it.

JD
Jane Doe
Student, Community College
Pro move: A letter avatar with good color and clean type is 100× better than a bad photo. Use one on placeholder profiles until you get a real headshot taken.
<!-- Load Phosphor once in your <head> -->
<script src="https://unpkg.com/@phosphor-icons/web"></script>

<!-- The interactive profile-card mockup — drop this anywhere -->
<div class="preview-wrap">

  <!-- LEFT: the live circle avatar, name and role -->
  <div class="preview-stage">
    <div id="previewAvatar">
      <span id="initialsText">JD</span>
    </div>
    <div id="previewName">Jane Doe</div>
    <div id="previewRole">Student, Community College</div>
  </div>

  <!-- RIGHT: the controls that drive the avatar -->
  <div class="preview-controls">
    <div class="control">
      <label>Your initials</label>
      <input id="inputInitials" type="text" maxlength="3" value="JD">
    </div>
    <div class="control">
      <label>Display name</label>
      <input id="inputName" type="text" value="Jane Doe">
    </div>
    <div class="control">
      <label>Role / title</label>
      <input id="inputRole" type="text" value="Student, Community College">
    </div>
    <div class="control">
      <label>Background color</label>
      <div class="swatches" id="swatches">
        <button class="active" data-color="linear-gradient(135deg, #ec4899, #8b5cf6)" style="background: linear-gradient(135deg, #ec4899, #8b5cf6);"></button>
        <button data-color="linear-gradient(135deg, #3b82f6, #06b6d4)" style="background: linear-gradient(135deg, #3b82f6, #06b6d4);"></button>
        <button data-color="linear-gradient(135deg, #10b981, #06b6d4)" style="background: linear-gradient(135deg, #10b981, #06b6d4);"></button>
        <button data-color="linear-gradient(135deg, #f59e0b, #ef4444)" style="background: linear-gradient(135deg, #f59e0b, #ef4444);"></button>
        <button data-color="linear-gradient(135deg, #1f2937, #374151)" style="background: linear-gradient(135deg, #1f2937, #374151);"></button>
        <button data-color="linear-gradient(135deg, #a855f7, #ec4899)" style="background: linear-gradient(135deg, #a855f7, #ec4899);"></button>
      </div>
    </div>
    <div class="control">
      <label>Expression</label>
      <select id="expressionPicker">
        <option value="initials">Initials (letter avatar)</option>
        <option value="ph-fill ph-smiley">Big smile</option>
        <option value="ph-fill ph-smiley-wink">Friendly wink</option>
        <option value="ph-fill ph-smiley-meh">Neutral (don't do this)</option>
        <option value="ph-fill ph-user-circle">Classic silhouette</option>
      </select>
    </div>
  </div>

</div>
/* Page basics so the dark card looks right out of the box */
* { box-sizing: border-box; margin: 0; padding: 0; }
body {
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  background: #0a0a0a;
  color: #f5f5f7;
  line-height: 1.6;
  padding: 40px 24px;
}

/* Two-column layout: avatar stage + controls */
.preview-wrap {
  display: grid;
  grid-template-columns: 280px 1fr;
  gap: 24px;
  max-width: 680px;
  margin: 0 auto;
}
@media (max-width: 720px) {
  .preview-wrap { grid-template-columns: 1fr; }
}

/* The stage that frames the live avatar */
.preview-stage {
  background: rgba(255,255,255,.03);
  border: 1px solid rgba(255,255,255,.08);
  border-radius: 12px;
  padding: 30px;
  text-align: center;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  min-height: 360px;
}

/* The circle crop — holds initials or a Phosphor icon */
#previewAvatar {
  width: 200px;
  height: 200px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 5rem;
  color: white;
  font-weight: 800;
  background: linear-gradient(135deg, #ec4899, #8b5cf6);
  border: 4px solid rgba(255,255,255,.1);
  transition: all .3s;
  box-shadow: 0 10px 30px rgba(0,0,0,.4);
}

/* Name under the circle */
#previewName {
  margin-top: 18px;
  font-size: 1.1rem;
  font-weight: 700;
  color: #f5f5f7;
}

/* Role / title under the name */
#previewRole {
  font-size: 0.85rem;
  color: #a1a1aa;
}

/* Stacked controls on the right */
.preview-controls {
  display: flex;
  flex-direction: column;
  gap: 16px;
}
.control {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.control label {
  font-size: 0.72rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: #a1a1aa;
}
.control input, .control select {
  background: #000;
  border: 1px solid rgba(255,255,255,.12);
  color: #f5f5f7;
  padding: 10px 14px;
  border-radius: 8px;
  font-family: inherit;
  font-size: 0.9rem;
}
.control input:focus, .control select:focus {
  outline: none;
  border-color: #ec4899;
}

/* Color swatch buttons */
.swatches { display: flex; gap: 8px; flex-wrap: wrap; }
.swatches button {
  width: 32px;
  height: 32px;
  border-radius: 50%;
  cursor: pointer;
  border: 2px solid rgba(255,255,255,.2);
  transition: transform .15s;
}
.swatches button:hover { transform: scale(1.15); }
.swatches button.active { border-color: #fff; transform: scale(1.15); }
// Grab the avatar pieces we want to update
const avatar   = document.getElementById('previewAvatar');
const initials = document.getElementById('initialsText');
const nameOut  = document.getElementById('previewName');
const roleOut  = document.getElementById('previewRole');

// Grab the controls that drive it
const inputInitials = document.getElementById('inputInitials');
const inputName     = document.getElementById('inputName');
const inputRole     = document.getElementById('inputRole');
const expr          = document.getElementById('expressionPicker');
const swatches      = document.getElementById('swatches');

// Typing new initials updates the circle (only in initials mode)
inputInitials.addEventListener('input', () => {
  if (expr.value === 'initials') {
    const cur = document.getElementById('initialsText');
    if (cur) cur.textContent = inputInitials.value.toUpperCase() || '?';
  }
});

// Name and role update live
inputName.addEventListener('input', () => { nameOut.textContent = inputName.value || 'Your Name'; });
inputRole.addEventListener('input', () => { roleOut.textContent = inputRole.value || 'Your Role'; });

// Switch between initials and a Phosphor face
expr.addEventListener('change', () => {
  if (expr.value === 'initials') {
    avatar.innerHTML = `<span id="initialsText">${inputInitials.value.toUpperCase() || '?'}</span>`;
  } else {
    avatar.innerHTML = `<i class="${expr.value}" style="font-size: 6rem;"></i>`;
  }
});

// Pick a background color from the swatches
swatches.addEventListener('click', e => {
  const btn = e.target.closest('button');
  if (!btn) return;
  swatches.querySelectorAll('button').forEach(b => b.classList.remove('active'));
  btn.classList.add('active');
  avatar.style.background = btn.dataset.color;
});
Step 6

Tools that do the hard work for you

You don't need Photoshop. These free tools handle cropping, background removal, and template design so your headshot looks polished in minutes.

Step 7

Your pre-upload checklist

Tick through this before you hit "save" on any profile. Your future self (and your recruiters) will thank you.

Full Page

The whole profile card as one file

Everything from this lab — the circular avatar, name, role, an expression switcher, and a color picker — combined into one complete HTML file. Copy it into a new file called profile.html, open it in a browser, and it just works. Here's the live result, then the full code.

Live preview

Complete HTML — copy this whole file

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>My Profile Card</title>
  <script src="https://unpkg.com/@phosphor-icons/web"></script>
  <style>
    * { box-sizing: border-box; margin: 0; padding: 0; }
    body {
      font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
      background: #0a0a0a; color: #f5f5f7; line-height: 1.6;
      min-height: 100vh; display: grid; place-items: center; padding: 40px 20px;
    }

    /* ===== Profile card ===== */
    .profile-card {
      background: rgba(255,255,255,.03); border: 1px solid rgba(255,255,255,.08);
      border-radius: 16px; padding: 34px 30px; text-align: center;
      max-width: 300px; width: 100%;
    }

    /* The circle that holds the avatar (initials or a Phosphor icon) */
    .profile-img {
      width: 180px; height: 180px; border-radius: 50%;   /* circle crop */
      margin: 0 auto; display: flex; align-items: center; justify-content: center;
      background: linear-gradient(135deg, #ec4899, #8b5cf6);
      border: 4px solid rgba(255,255,255,.1);
      box-shadow: 0 10px 30px rgba(0,0,0,.4);
      font-size: 4rem; font-weight: 800; color: #fff;
      transition: background .3s;
    }
    .profile-img i { font-size: 5rem; color: #fff; }

    .profile-name { margin-top: 18px; font-size: 1.2rem; font-weight: 700; color: #f5f5f7; }
    .profile-role { font-size: 0.85rem; color: #a1a1aa; margin-top: 4px; }

    /* ===== Controls ===== */
    .controls { display: grid; gap: 14px; margin-top: 24px; text-align: left; }
    .control label {
      display: block; font-size: 0.68rem; font-weight: 700; text-transform: uppercase;
      letter-spacing: 0.1em; color: #a1a1aa; margin-bottom: 6px;
    }
    .control input, .control select {
      width: 100%; background: #000; border: 1px solid rgba(255,255,255,.12);
      color: #f5f5f7; padding: 10px 14px; border-radius: 8px;
      font-family: inherit; font-size: 0.9rem;
    }
    .control input:focus, .control select:focus { outline: none; border-color: #ec4899; }

    .swatches { display: flex; gap: 8px; flex-wrap: wrap; }
    .swatches button {
      width: 32px; height: 32px; border-radius: 50%; cursor: pointer;
      border: 2px solid rgba(255,255,255,.2); transition: transform .15s;
    }
    .swatches button:hover, .swatches button.active { transform: scale(1.15); border-color: #fff; }
  </style>
</head>
<body>

  <div class="profile-card">
    <!-- Circle avatar: shows initials by default -->
    <div class="profile-img" id="avatar"><span id="initials">JD</span></div>
    <h3 class="profile-name" id="name">Jane Doe</h3>
    <p class="profile-role" id="role">Student, Community College</p>

    <div class="controls">
      <div class="control">
        <label for="inInitials">Your initials</label>
        <input id="inInitials" type="text" maxlength="3" value="JD">
      </div>
      <div class="control">
        <label for="inName">Display name</label>
        <input id="inName" type="text" value="Jane Doe">
      </div>
      <div class="control">
        <label for="inRole">Role / title</label>
        <input id="inRole" type="text" value="Student, Community College">
      </div>
      <div class="control">
        <label>Background color</label>
        <div class="swatches" id="swatches">
          <button class="active" data-color="linear-gradient(135deg, #ec4899, #8b5cf6)" style="background: linear-gradient(135deg, #ec4899, #8b5cf6);"></button>
          <button data-color="linear-gradient(135deg, #3b82f6, #06b6d4)" style="background: linear-gradient(135deg, #3b82f6, #06b6d4);"></button>
          <button data-color="linear-gradient(135deg, #10b981, #06b6d4)" style="background: linear-gradient(135deg, #10b981, #06b6d4);"></button>
          <button data-color="linear-gradient(135deg, #f59e0b, #ef4444)" style="background: linear-gradient(135deg, #f59e0b, #ef4444);"></button>
          <button data-color="linear-gradient(135deg, #1f2937, #374151)" style="background: linear-gradient(135deg, #1f2937, #374151);"></button>
        </div>
      </div>
      <div class="control">
        <label for="inExpr">Expression</label>
        <select id="inExpr">
          <option value="initials">Initials (letter avatar)</option>
          <option value="ph-fill ph-smiley">Big smile</option>
          <option value="ph-fill ph-smiley-wink">Friendly wink</option>
          <option value="ph-fill ph-smiley-meh">Neutral (don't do this)</option>
          <option value="ph-fill ph-user-circle">Classic silhouette</option>
        </select>
      </div>
    </div>
  </div>

  <script>
    var avatar   = document.getElementById('avatar');
    var inInit   = document.getElementById('inInitials');
    var inName   = document.getElementById('inName');
    var inRole   = document.getElementById('inRole');
    var inExpr   = document.getElementById('inExpr');
    var swatches = document.getElementById('swatches');

    function paintAvatar() {
      if (inExpr.value === 'initials') {
        avatar.innerHTML = '<span>' + (inInit.value.toUpperCase() || '?') + '</span>';
      } else {
        avatar.innerHTML = '<i class="' + inExpr.value + '"></i>';
      }
    }

    inInit.addEventListener('input', paintAvatar);
    inExpr.addEventListener('change', paintAvatar);
    inName.addEventListener('input', function () {
      document.getElementById('name').textContent = inName.value || 'Your Name';
    });
    inRole.addEventListener('input', function () {
      document.getElementById('role').textContent = inRole.value || 'Your Role';
    });

    swatches.addEventListener('click', function (e) {
      var btn = e.target.closest('button');
      if (!btn) return;
      swatches.querySelectorAll('button').forEach(function (b) { b.classList.remove('active'); });
      btn.classList.add('active');
      avatar.style.background = btn.dataset.color;
    });
  </script>
</body>
</html>
That's a real, standalone page. The live preview above is rendered from the exact code in the box — so what you copy is precisely what you see.
Your Turn

The 15-minute assignment

Pick one of the tools above and create your profile picture today. Here's a quick path:

  1. Take 10–20 photos near a bright window. Mix serious and smiling shots.
  2. Pick your favorite 3. Upload them to remove.bg for clean backgrounds.
  3. Drop the best one into the Canva class template.
  4. Add a solid color or subtle gradient background that matches your personality but not your outfit.
  5. Export at 400×400 minimum, upload to LinkedIn, Slack, GitHub, and your portfolio — use the same image everywhere.
Remember: done is better than perfect. A decent smiling photo you upload today beats the "amazing" one you keep meaning to take. You can always update it in six months.