diff --git a/docs/components/alert.md b/docs/components/alert.md
index d89679bb..662dc4a2 100644
--- a/docs/components/alert.md
+++ b/docs/components/alert.md
@@ -4,7 +4,71 @@
 
 Alerts are used to display important messages.
 
-Alerts are designed to be shown dynamically, so you need to include the `open` attribute to display them.
+Alerts are designed to be shown dynamically, so you must include the `open` attribute to display them.
+
+
+
+
+
+```html preview
+<div class="toast-example">
+  <sl-button type="primary">Primary</sl-button>
+  <sl-button type="success">Success</sl-button>
+  <sl-button type="info">Info</sl-button>
+  <sl-button type="warning">Warning</sl-button>
+  <sl-button type="danger">Danger</sl-button>
+  
+  <sl-alert type="primary" placement="top-end" duration="3000" closable>
+    <sl-icon slot="icon" name="info-circle"></sl-icon>
+    <strong>This is super informative</strong><br>
+    You can tell by how pretty the alert is.
+  </sl-alert>
+
+  <sl-alert type="success" placement="top-end" duration="3000" closable>
+    <sl-icon slot="icon" name="check2-circle"></sl-icon>
+    <strong>Your changes have been saved</strong><br>
+    You can safely exit the app now.
+  </sl-alert>
+
+  <sl-alert type="info" placement="top-end" duration="3000" closable>
+    <sl-icon slot="icon" name="gear"></sl-icon>
+    <strong>Your settings have been updated</strong><br>
+    Some settings will take affect the next time you log in.
+  </sl-alert>
+
+  <sl-alert type="warning" placement="top-end" duration="3000" closable>
+    <sl-icon slot="icon" name="exclamation-triangle"></sl-icon>
+    <strong>Your session has ended</strong><br>
+    Please login again to continue.
+  </sl-alert>
+
+  <sl-alert type="danger" placement="bottom" duration="3000" closable>
+    <sl-icon slot="icon" name="exclamation-octagon"></sl-icon>
+    <strong>Your account has been deleted</strong><br>
+    We're very sorry to see you go!
+  </sl-alert>
+</div>
+
+<script>
+  const container = document.querySelector('.toast-example');
+
+  ['primary', 'success', 'info', 'warning', 'danger'].map(type => {
+    const button = container.querySelector(`sl-button[type="${type}"]`);
+    const alert = container.querySelector(`sl-alert[type="${type}"]`);
+
+    button.addEventListener('click', () => alert.show());
+  });
+</script>
+```
+
+
+
+
+
+
+
+
+
 
 ```html preview
 <sl-alert open>
@@ -46,16 +110,16 @@ Set the `type` attribute to change the alert's type.
 
 <sl-alert type="warning" open>
   <sl-icon slot="icon" name="exclamation-triangle"></sl-icon>
-  <strong>This will end your session</strong><br>
-  You will be logged out until you log in again.
+  <strong>Your session has ended</strong><br>
+  Please login again to continue.
 </sl-alert>
 
 <br>
 
 <sl-alert type="danger" open>
   <sl-icon slot="icon" name="exclamation-octagon"></sl-icon>
-  <strong>Delete this file?</strong><br>
-  This is permanent, which means forever!
+    <strong>Your account has been deleted</strong><br>
+    We're very sorry to see you go!
 </sl-alert>
 ```
 
diff --git a/docs/tokens/z-index.md b/docs/tokens/z-index.md
index 41d6f346..c596a5d7 100644
--- a/docs/tokens/z-index.md
+++ b/docs/tokens/z-index.md
@@ -7,4 +7,5 @@ Z-indexes are used to stack components in a logical manner.
 | `--sl-z-index-drawer`        | 700   |
 | `--sl-z-index-dialog`        | 800   |
 | `--sl-z-index-dropdown`      | 900   |
+| `--sl-z-index-alert-group`   | 950   |
 | `--sl-z-index-tooltip`       | 1000  |
diff --git a/src/components.d.ts b/src/components.d.ts
index c108421b..940bf845 100644
--- a/src/components.d.ts
+++ b/src/components.d.ts
@@ -11,6 +11,10 @@ export namespace Components {
           * Set to true to make the alert closable.
          */
         "closable": boolean;
+        /**
+          * The length of time, in milliseconds, the alert will show before closing itself.
+         */
+        "duration": number;
         /**
           * Hides the alert
          */
@@ -19,6 +23,10 @@ export namespace Components {
           * Indicates whether or not the alert is open. You can use this in lieu of the show/hide methods.
          */
         "open": boolean;
+        /**
+          * Determines how the alert will be shown. If this is anything other than `inline`, the alert will be shown in a stack as a "toast" notification. When the alert is shown as a notification, it will be hoisted to a stack and removed from the DOM when hidden. (You can reuse alerts that have been removed by storing a reference to the element.)
+         */
+        "placement": 'inline' | 'top-start' | 'top' | 'top-end' | 'bottom-start' | 'bottom' | 'bottom-end';
         /**
           * Shows the alert.
          */
@@ -1418,6 +1426,10 @@ declare namespace LocalJSX {
           * Set to true to make the alert closable.
          */
         "closable"?: boolean;
+        /**
+          * The length of time, in milliseconds, the alert will show before closing itself.
+         */
+        "duration"?: number;
         /**
           * Emitted after the alert closes and all transitions are complete.
          */
@@ -1438,6 +1450,10 @@ declare namespace LocalJSX {
           * Indicates whether or not the alert is open. You can use this in lieu of the show/hide methods.
          */
         "open"?: boolean;
+        /**
+          * Determines how the alert will be shown. If this is anything other than `inline`, the alert will be shown in a stack as a "toast" notification. When the alert is shown as a notification, it will be hoisted to a stack and removed from the DOM when hidden. (You can reuse alerts that have been removed by storing a reference to the element.)
+         */
+        "placement"?: 'inline' | 'top-start' | 'top' | 'top-end' | 'bottom-start' | 'bottom' | 'bottom-end';
         /**
           * The type of alert.
          */
diff --git a/src/components/alert/alert.light-dom.scss b/src/components/alert/alert.light-dom.scss
new file mode 100644
index 00000000..ec1238c1
--- /dev/null
+++ b/src/components/alert/alert.light-dom.scss
@@ -0,0 +1,49 @@
+:root {
+  --width: 28rem;
+  --spacing: var(--sl-spacing-medium);
+}
+
+.sl-alert-stack {
+  position: fixed;
+  z-index: var(--sl-z-index-toast);
+  width: var(--width);
+  max-width: 100%;
+  max-height: 100%;
+  overflow: auto;
+  padding: 0 var(--spacing);
+
+  sl-alert {
+    --box-shadow: var(--sl-shadow-large);
+    margin: var(--spacing) 0;
+  }
+}
+
+.sl-alert-stack[data-placement='top-start'] {
+  top: 0;
+  left: 0;
+}
+
+.sl-alert-stack[data-placement='top'] {
+  top: 0;
+  left: calc(50% - var(--width) / 2);
+}
+
+.sl-alert-stack[data-placement='top-end'] {
+  top: 0;
+  right: 0;
+}
+
+.sl-alert-stack[data-placement='bottom-start'] {
+  bottom: 0;
+  left: 0;
+}
+
+.sl-alert-stack[data-placement='bottom'] {
+  bottom: 0;
+  left: calc(50% - var(--width) / 2);
+}
+
+.sl-alert-stack[data-placement='bottom-end'] {
+  bottom: 0;
+  right: 0;
+}
diff --git a/src/components/alert/alert.scss b/src/components/alert/alert.scss
index 4911db01..d060ef76 100644
--- a/src/components/alert/alert.scss
+++ b/src/components/alert/alert.scss
@@ -1,6 +1,11 @@
 @import 'component';
 
+/**
+ * @prop --box-shadow: The alert's box shadow.
+ */
 :host {
+  --box-shadow: none;
+
   display: block;
 
   &[hidden] {
@@ -16,17 +21,20 @@
   border: solid 1px var(--sl-color-gray-90);
   border-top-width: 3px;
   border-radius: var(--sl-border-radius-medium);
+  box-shadow: var(--box-shadow);
   font-family: var(--sl-font-sans);
   font-size: var(--sl-font-size-small);
   font-weight: var(--sl-font-weight-normal);
   line-height: 1.6;
   color: var(--sl-color-gray-30);
   opacity: 0;
-  transition: var(--sl-transition-medium) opacity ease;
+  transform: scale(0.9);
+  transition: var(--sl-transition-medium) opacity ease, var(--sl-transition-medium) transform ease;
 }
 
 .alert--open {
   opacity: 1;
+  transform: scale(1);
 }
 
 .alert__icon {
@@ -91,5 +99,5 @@
   display: flex;
   align-items: center;
   font-size: var(--sl-font-size-large);
-  padding: 0 var(--sl-spacing-medium);
+  padding-right: var(--sl-spacing-medium);
 }
diff --git a/src/components/alert/alert.tsx b/src/components/alert/alert.tsx
index 9fcf4b1a..3e9c87c1 100644
--- a/src/components/alert/alert.tsx
+++ b/src/components/alert/alert.tsx
@@ -13,6 +13,8 @@ import { Component, Element, Event, EventEmitter, Host, Method, Prop, Watch, h }
  * @part close-button - The close button.
  */
 
+const stack = Object.assign(document.createElement('div'), { className: 'sl-alert-stack' });
+
 @Component({
   tag: 'sl-alert',
   styleUrl: 'alert.scss',
@@ -20,6 +22,7 @@ import { Component, Element, Event, EventEmitter, Host, Method, Prop, Watch, h }
 })
 export class Alert {
   alert: HTMLElement;
+  autoHideTimeout: any;
   isShowing = false;
 
   @Element() host: HTMLSlAlertElement;
@@ -33,11 +36,31 @@ export class Alert {
   /** The type of alert. */
   @Prop() type: 'primary' | 'success' | 'info' | 'warning' | 'danger' = 'primary';
 
+  /**
+   * Determines how the alert will be shown. If this is anything other than `inline`, the alert will be shown in a stack
+   * as a "toast" notification. When the alert is shown as a notification, it will be hoisted to a stack and removed
+   * from the DOM when hidden. (You can reuse alerts that have been removed by storing a reference to the element.)
+   */
+  @Prop() placement: 'inline' | 'top-start' | 'top' | 'top-end' | 'bottom-start' | 'bottom' | 'bottom-end' = 'inline';
+
+  /** The length of time, in milliseconds, the alert will show before closing itself. */
+  @Prop() duration = Infinity;
+
   @Watch('open')
   handleOpenChange() {
     this.open ? this.show() : this.hide();
   }
 
+  @Watch('duration')
+  handleDurationChange() {
+    clearTimeout(this.autoHideTimeout);
+
+    // Restart the timeout if the duration changes and the alert is open
+    if (this.open && this.duration < Infinity) {
+      this.autoHideTimeout = setTimeout(() => this.hide(), this.duration);
+    }
+  }
+
   /** Emitted when the alert opens. Calling `event.preventDefault()` will prevent it from being opened. */
   @Event() slShow: EventEmitter;
 
@@ -80,6 +103,14 @@ export class Alert {
     this.host.clientWidth; // force a reflow
     this.isShowing = true;
     this.open = true;
+
+    if (this.placement !== 'inline') {
+      this.appendToStack();
+    }
+
+    if (this.duration < Infinity) {
+      this.autoHideTimeout = setTimeout(() => this.hide(), this.duration);
+    }
   }
 
   /** Hides the alert */
@@ -96,6 +127,7 @@ export class Alert {
       return;
     }
 
+    clearTimeout(this.autoHideTimeout);
     this.isShowing = false;
     this.open = false;
   }
@@ -110,10 +142,34 @@ export class Alert {
     // Ensure we only emit one event when the target element is no longer visible
     if (event.propertyName === 'opacity' && target.classList.contains('alert')) {
       this.host.hidden = !this.open;
+
+      if (this.placement !== 'inline' && !this.open) {
+        this.removeFromStack();
+      }
+
       this.open ? this.slAfterShow.emit() : this.slAfterHide.emit();
     }
   }
 
+  appendToStack() {
+    if (!stack.parentElement) {
+      document.body.append(stack);
+    }
+
+    stack.dataset.placement = this.placement;
+    stack.append(this.host);
+  }
+
+  removeFromStack() {
+    this.host.remove();
+
+    // Remove the stack from the DOM when there are no more alerts
+    const openAlerts = [...stack.querySelectorAll('sl-alert')].filter((el: HTMLSlAlertElement) => el.open === true);
+    if (openAlerts.length === 0) {
+      stack.remove();
+    }
+  }
+
   render() {
     return (
       <Host hidden>
@@ -145,7 +201,9 @@ export class Alert {
           </span>
 
           {this.closable && (
-            <sl-icon-button part="close-button" class="alert__close" name="x" onClick={this.handleCloseClick} />
+            <span class="alert__close">
+              <sl-icon-button part="close-button" name="x" onClick={this.handleCloseClick} />
+            </span>
           )}
         </div>
       </Host>
diff --git a/src/styles/shoelace.scss b/src/styles/shoelace.scss
index 1e0fa5c4..b00b8e9a 100644
--- a/src/styles/shoelace.scss
+++ b/src/styles/shoelace.scss
@@ -249,6 +249,7 @@
   --sl-z-index-drawer: 700;
   --sl-z-index-dialog: 800;
   --sl-z-index-dropdown: 900;
+  --sl-z-index-toast: 950;
   --sl-z-index-tooltip: 1000;
 }
 
@@ -268,4 +269,5 @@
 // Component light DOM styles - only follow this pattern when absolutely necessary!
 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 
+@import '../components/alert/alert.light-dom';
 @import '../components/button-group/button-group.light-dom';