DEV Community

Cover image for Angular vs Svelte - Card Component
Mauro Garcia
Mauro Garcia

Posted on Edited on Originally published at maurogarcia.dev

Angular vs Svelte - Card Component

If you check out some of my previous posts, you'll know that I've been doing some experiments with Svelte and Sapper lately.

As I've been working with Angular for years and now I'm learning Svelte by doing, I thought it could be useful to migrate some of my components from Angular to Svelte.

In this article, I'll share the following card component built both with Angular and Svelte so you can see the differences:

Alt text of image

I'm using tailwindcss as my utility-first CSS framework. If you're not familiar with tailwind, please checkout the official tailwindcss site. Also, if you want to start using tailwindcss with angular or with Svelte, I wrote the following articles:

Angular

For the Angular version of this card component, we'll need to create a post-card component like this:

// post-card.component.ts

import { Component, Input } from '@angular/core'

@Component({
    selector: 'post-card',
    templateUrl: './post-card.component.html',
    styleUrls: ['./post-card.component.css']
})

export class PostCardComponent {

    @Input() title;
    @Input() description;
    @Input() location;
    @Input() picUrl = 'https://i1.wp.com/www.foot.com/wp-content/uploads/2017/03/placeholder.gif?ssl=1'
    @Input() createdAt;
    @Input() labels = [];

    constructor() { }

    showMore() {
        alert("showing more...")
    }
}
ðŸ”ī Hot News: mauro codes/angular vs svelte card component nk - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ” ðŸ”ī Hot News: mauro codes/angular vs svelte card component nk - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ”
  • The @Input() decorator allow us to share data between components. An @Input() property is writable while an @Output() property is observable.
<!-- post-card.component.html -->

<div class="flex flex-wrap shadow-lg rounded-lg overflow-hidden mb-6">
    <!-- Image -->
    <div class="w-full h-48 md:h-auto md:w-1/4 bg-cover bg-center" [style.backgroundImage]="'url('+ picUrl +')'"></div>
    <!-- Details -->
    <div class="w-full md:w-3/4 px-6 py-4 bg-white">
        <div class="py-2">
            <p class="text-2xl">{{title}}</p>
            <p class="text-sm text-gray-600 mb-2">{{createdAt | date:'MM/dd/yyyy'}}</p>
            <!-- Labels -->
            <div class="flex flex-wrap">
                <p *ngFor="let label of labels"
                    class="border border-solid border-orange-500 rounded w-auto inline-block px-2 py-1 mr-3 text-sm mb-2">
                    {{label}}
                </p>
            </div>
        </div>
        <p class="flex items-center text-sm mb-4">
            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24">
                <path class="heroicon-ui"
                    d="M4.06 13a8 8 0 0 0 5.18 6.51A18.5 18.5 0 0 1 8.02 13H4.06zm0-2h3.96a18.5 18.5 0 0 1 1.22-6.51A8 8 0 0 0 4.06 11zm15.88 0a8 8 0 0 0-5.18-6.51A18.5 18.5 0 0 1 15.98 11h3.96zm0 2h-3.96a18.5 18.5 0 0 1-1.22 6.51A8 8 0 0 0 19.94 13zm-9.92 0c.16 3.95 1.23 7 1.98 7s1.82-3.05 1.98-7h-3.96zm0-2h3.96c-.16-3.95-1.23-7-1.98-7s-1.82 3.05-1.98 7zM12 22a10 10 0 1 1 0-20 10 10 0 0 1 0 20z" />
                </svg>
            <span class="ml-2">{{location}}</span>
        </p>
        <p class="mb-4">{{description}}</p>
        <div class="flex flex-wrap md:flex-row-reverse">
            <button (click)="showMore()"
                class="w-full md:ml-2 px-4 py-3 rounded bg-orange-600 hover:bg-orange-500 mb-2 md:w-auto md:mb-0 text-white">
                Show more
            </button>
        </div>
    </div>
</div>
ðŸ”ī Hot News: mauro codes/angular vs svelte card component nk - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ” ðŸ”ī Hot News: mauro codes/angular vs svelte card component nk - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ”
  • I'm using pipes to change the date format. A pipe takes in data as input and transforms it to a desired output. In this case, I'm transforming a javascript date to 'MM/dd/yyyy'.
  • Data binding is achieved by using double curly braces like this: {{yourProperty}}
  • To setup an image as a background-image within the card, I'm using property binding like this: [style.backgroundImage]="'url('+ picUrl +')'"
  • NgFor is a structural directive that renders a template for each item in a collection. In this case, I'm using it to iterate through each label like this:
<p *ngFor="let label of labels" class="border border-solid border-orange-500 rounded w-auto inline-block px-2 py-1 mr-3 text-sm mb-2">
  {{label}}
</p>
ðŸ”ī Hot News: mauro codes/angular vs svelte card component nk - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ” ðŸ”ī Hot News: mauro codes/angular vs svelte card component nk - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ”

Usage

In order to display our post-card component, I'm adding a card property in the AppComponent like this:

// app.component.ts

import { Component } from '@angular/core'

@Component({
    selector: 'app-root',
    templateUrl: './app.component.html',
    styleUrls: ['./app.component.css']
})

export class AppComponent {
  // This data will be sent to our post-card component
  card = {
    title: "Lorem ipsum dolor sit amet, consectetur adipiscing elit",
    description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum",
    location: "New York",
    picUrl: "https://images.pexels.com/photos/1060803/pexels-photo-1060803.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=750&w=1260",
    createdAt: new Date(),
    labels: ["Travel", "People"]
  }

  constructor() { }
  }
}

ðŸ”ī Hot News: mauro codes/angular vs svelte card component nk - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ” ðŸ”ī Hot News: mauro codes/angular vs svelte card component nk - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ”
<!-- app.component.html -->
<post-card  [title]="card.title" 
            [description]="card.description"
            [location]="card.location"
            [picUrl]="card.picUrl"
            [createdAt]="card.createdAt"
            [labels]="card.labels">
</post-card>
ðŸ”ī Hot News: mauro codes/angular vs svelte card component nk - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ” ðŸ”ī Hot News: mauro codes/angular vs svelte card component nk - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ”
  • This time, I'm using property binding to send data from AppComponent to PostCardComponent.

Svelte

Now, let's use Svelte to build exactly the same component

<!-- PostCard.svelte -->

<script>
  export let title
  export let description
  export let location
  export let picUrl = 'https://i1.wp.com/www.foot.com/wp-content/uploads/2017/03/placeholder.gif?ssl=1'
  export let createdAt
  export let labels = []

  function showMore() {
    alert("Showing more...")
  }
</script>

<div class="flex flex-wrap shadow-lg rounded-lg overflow-hidden mb-6">
  <!-- Image -->
  <div class="w-full h-48 md:h-auto md:w-1/4 bg-cover bg-center" style="background-image: url('{picUrl}')"></div>
  <!-- Details -->
  <div class="w-full md:w-3/4 px-6 py-4 bg-white">
    <div class="py-2">
      <p class="text-2xl">{title}</p>
      <p class="text-sm text-gray-600 mb-2">{createdAt.toLocaleDateString()}</p>
      <!-- Labels -->
      <div class="flex flex-wrap">
        {#each labels as label}
          <p
            class="border border-solid border-orange-500 rounded w-auto inline-block px-2 py-1 mr-3 text-sm mb-2">
            {label}
          </p>
        {/each}
      </div>
    </div>
    <p class="flex items-center text-sm mb-4">
        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path class="heroicon-ui" d="M4.06 13a8 8 0 0 0 5.18 6.51A18.5 18.5 0 0 1 8.02 13H4.06zm0-2h3.96a18.5 18.5 0 0 1 1.22-6.51A8 8 0 0 0 4.06 11zm15.88 0a8 8 0 0 0-5.18-6.51A18.5 18.5 0 0 1 15.98 11h3.96zm0 2h-3.96a18.5 18.5 0 0 1-1.22 6.51A8 8 0 0 0 19.94 13zm-9.92 0c.16 3.95 1.23 7 1.98 7s1.82-3.05 1.98-7h-3.96zm0-2h3.96c-.16-3.95-1.23-7-1.98-7s-1.82 3.05-1.98 7zM12 22a10 10 0 1 1 0-20 10 10 0 0 1 0 20z"/></svg>
        <span class="ml-2">{location}</span>
    </p>
    <p class="mb-4">{description}</p>
    <div class="flex flex-wrap md:flex-row-reverse">
      <button
        on:click={showMore}
        class="w-full md:ml-2 px-4 py-3 rounded bg-orange-600 hover:bg-orange-500 mb-2 md:w-auto md:mb-0 text-white">
        Show more
      </button>
    </div>
  </div>
</div>
ðŸ”ī Hot News: mauro codes/angular vs svelte card component nk - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ” ðŸ”ī Hot News: mauro codes/angular vs svelte card component nk - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ”
  • Instead of using pipes, I'm formatting the javascript Date using {createdAt.toLocaleDateString()}.
  • Data binding is achieved by using single curly braces like this: {yourProperty}
  • To setup an image as a background-image within the card, I'm using data binding like this: style="background-image: url('{picUrl}')"
  • Instead of using structural directives for looping through items, Svelte use each blocks:
{#each labels as label}
  <p class="border border-solid border-orange-500 rounded w-auto inline-block px-2 py-1 mr-3 text-sm mb-2">
    {label}
  </p>
{/each}
ðŸ”ī Hot News: mauro codes/angular vs svelte card component nk - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ” ðŸ”ī Hot News: mauro codes/angular vs svelte card component nk - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ”

Usage

<!-- OtherSvelteComponent.Svelte -->
<script>
    import PostCard from "../components/PostCard.svelte";
    // This data will be sent to our post-card component
    const card = {
        title: "Lorem ipsum dolor sit amet, consectetur adipiscing elit",
        description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum",
        location: "New York",
        picUrl: "https://images.pexels.com/photos/1060803/pexels-photo-1060803.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=750&w=1260",
        createdAt: new Date(),
        labels: ["Travel", "People"]
    }

</script>

<PostCard {...card} />
ðŸ”ī Hot News: mauro codes/angular vs svelte card component nk - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ” ðŸ”ī Hot News: mauro codes/angular vs svelte card component nk - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ”

Final thoughts

As you probably noticed, the Svelte implementation is smaller. To be more precise, it's 20% smaller: 2348 characters (Svelte) against 2817 (Angular).
You may think that 20% isn't a big difference, but the smaller the components are, the greater will be the difference between both implementations.
To prove that point, let's see a super basic example:

// Angular - HelloWorld component
import { Component } from '@angular/core';

@Component({
  selector: 'hello-world',
  template: '<p>{{message}}</p>',
  styleUrls: ['./hello-world.component.css']
})
export class HelloWorldComponent {

  message = "Hello world"

  constructor() { }
}
ðŸ”ī Hot News: mauro codes/angular vs svelte card component nk - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ” ðŸ”ī Hot News: mauro codes/angular vs svelte card component nk - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ”
<!-- Svelte - HelloWorld component -->

<script>
  let message = "Hello world"
</script>

<p>{message}</p>
ðŸ”ī Hot News: mauro codes/angular vs svelte card component nk - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ” ðŸ”ī Hot News: mauro codes/angular vs svelte card component nk - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ”

In this case, the Svelte component is 400% smaller: 224 characters (Angular) against 59. And that's the added value! By keeping your components as small and atomic as possible, you'll be writing much less code.

What do you think about Svelte? Have you tried it yet?

Let me know in the comments below!

Top comments (20)

ðŸ”ī Hot News: mauro codes/angular vs svelte card component nk - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ”
 
gc_psk profile image
Giancarlo Buomprisco •

Counting characters to compare a fairly simple components is way too naive as a comparison: I do like both Angular and Svelte, so I don't think I am biased when I say this. I'd like to see the comparison of two full-blown complex, real world apps. Only then we can probably compare them.

ðŸ”ī Hot News: mauro codes/angular vs svelte card component nk - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ”
 
johncarroll profile image
John Carroll •

Well, as someone who's only familiar with Angular, I can say that I find these comparisons interesting and useful.

But for folks like you, there's a website delivering exactly what you're asked for: github.com/gothinkster/realworld

ðŸ”ī Hot News: mauro codes/angular vs svelte card component nk - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ”
 
gc_psk profile image
Giancarlo Buomprisco • • Edited

I agree: they're useful, I made one myself, but I wouldn't use counting characters as a metric for comparison. There's so much more in an application than components, which in my opinion are the "easy" part. The real world app you link is hardly one: I'm talking enterprise, resilient, rock-solid stuff. Probably not something you can find in the open, I admit.

ðŸ”ī Hot News: mauro codes/angular vs svelte card component nk - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ” Thread
 
mauro_codes profile image
Mauro Garcia •

I think your point is valid, but not all the apps are enterprise or super complex. And, for those kind of apps it's helpful to see this kind of comparisons. Btw, I love Angular and I'm using it on most of my projects.

As I said on previous posts, I'm just starting with Svelte and Sapper. Maybe in the feature I'll be comparing more complex stuff, but this series are all about components.

They are probably the easy part, but they are also a big part of the code we write every date.

ðŸ”ī Hot News: mauro codes/angular vs svelte card component nk - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ”
 
mauro_codes profile image
Mauro Garcia •

Glad it was useful for you! 😄

ðŸ”ī Hot News: mauro codes/angular vs svelte card component nk - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ”
 
Sloan, the sloth mascot
Comment deleted
ðŸ”ī Hot News: mauro codes/angular vs svelte card component nk - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ”
 
gc_psk profile image
Giancarlo Buomprisco •

As I said in another comment, that's hardly a real world app. A more complex todo app at best.

ðŸ”ī Hot News: mauro codes/angular vs svelte card component nk - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ”
 
adamwakif profile image
Adam WaƘiƑ •

I m a react developer .. i kicked React in the trash because of Svelte .. i love it 😍.. Svelte became my new girlfriend 😂😂

ðŸ”ī Hot News: mauro codes/angular vs svelte card component nk - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ”
 
ghost profile image
Ghost •

Id like to do the same but the lack of good ts support made us break up

ðŸ”ī Hot News: mauro codes/angular vs svelte card component nk - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ”
 
mauro_codes profile image
Mauro Garcia •

Did you try svelte with sapper?

ðŸ”ī Hot News: mauro codes/angular vs svelte card component nk - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ”
 
seanmclem profile image
Seanmclem •

How does svelte handle css?

ðŸ”ī Hot News: mauro codes/angular vs svelte card component nk - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ”
 
ghost profile image
Ghost • • Edited

U just use a <style> tag (and it scopes it automatically)

ðŸ”ī Hot News: mauro codes/angular vs svelte card component nk - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ”
 
seanmclem profile image
Seanmclem •

Nice. Does it support separate files? If that's your thing

ðŸ”ī Hot News: mauro codes/angular vs svelte card component nk - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ” Thread
 
ghost profile image
Ghost •

Tbh i have no idea

ðŸ”ī Hot News: mauro codes/angular vs svelte card component nk - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ” Thread
 
doomd profile image
Doomd •

It does. css-tricks.com/what-i-like-about-w...

ðŸ”ī Hot News: mauro codes/angular vs svelte card component nk - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ”
 
doomd profile image
Doomd •

I'd just like to add, that it took me about 9 days to do one website with React back in December 2019. I was able to refactor the entire website in Svelte in less than a day. Obviously refactoring an existing site is alot easier than building from scratch, but I mention this to illustrate the ease with which you can transition. The new Svelte site used 63% of the code that React did, and my Google PageSpeed score for that site went from 87 (mobile) to 99 (mobile). For web projects, I LOVE Svelte.

ðŸ”ī Hot News: mauro codes/angular vs svelte card component nk - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ”
 
juancarlospaco profile image
Juan Carlos •

Svelte is superior and a better saner approach with more future-proof concept.
I prefer Nim tho.

ðŸ”ī Hot News: mauro codes/angular vs svelte card component nk - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ”
 
mackelito profile image
Markus Thiel •

To make it more fair should not styleUrls: ['./hello-world.component.css'] be removed?

ðŸ”ī Hot News: mauro codes/angular vs svelte card component nk - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ”
 
diogenespolanco profile image
DiÃģgenes Polanco •

I love that way of developing man.

ðŸ”ī Hot News: mauro codes/angular vs svelte card component nk - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ”
 
mauro_codes profile image
Mauro Garcia •

Thanks! 😄