Skip to main content
Layers are the fundamental building blocks for organizing visual content in Aseprite. They allow you to separate different elements of your artwork, making it easier to edit and animate complex scenes.

What are Layers?

A layer is a transparent sheet that can contain images (cels) at different frames. Layers are stacked on top of each other, with content from upper layers appearing in front of lower layers.
Layers are organized in a hierarchy - you can have layer groups that contain other layers, creating a tree-like structure.

Layer Types

Aseprite has three main types of layers:

Image Layers

The most common layer type - contains pixel data (images) at various frames.
local sprite = Sprite(32, 32)
local layer = sprite:newLayer()  -- Creates an image layer
print(layer:isImage())  -- true

Layer Groups

Containers that organize other layers into a hierarchy.
local sprite = Sprite(32, 32)
local group = sprite:newGroup()  -- Creates a layer group
print(group:isGroup())  -- true

-- Add layers to the group
local childLayer = sprite:newLayer()
childLayer.parent = group

Tilemap Layers

Special layers that reference tiles from a tileset instead of storing full pixel data.
local layer = sprite.layers[1]
if layer:isTilemap() then
  print("This is a tilemap layer")
end

Layer Properties

Basic Properties

local sprite = Sprite(32, 32)
local layer = sprite.layers[1]

-- Layer name
print(layer.name)  -- "Layer 1" (default)
layer.name = "Character"

-- Parent (sprite or layer group)
print(layer.parent)  -- Returns parent group or sprite

Blend Mode and Opacity

Control how the layer blends with layers below it:
local sprite = Sprite(32, 64)
local layer = sprite.layers[1]

-- Opacity (0-255)
print(layer.opacity)  -- 255 (fully opaque)
layer.opacity = 128  -- 50% transparent

-- Blend mode
print(layer.blendMode)  -- BlendMode.NORMAL (default)
layer.blendMode = BlendMode.MULTIPLY
layer.blendMode = BlendMode.SCREEN

Layer Flags

Layers have several flags that control their behavior:

Background Layer

A special locked layer that represents the opaque background:
local layer = sprite.layers[1]

-- Check if background
if layer:isBackground() then
  print("This is a background layer")
end

-- Convert to background layer
layer:setBackground(true)
print(layer:isMovable())  -- false (background layers can't move)
Background layers are always at the bottom of the layer stack and cannot be moved or deleted easily.

Continuous Layers

Prefer to link cels when copying:
local layer = sprite.layers[1]

-- Enable continuous mode
layer:setContinuous(true)
print(layer:isContinuous())  -- true

Reference Layers

Special layers used as visual reference that don’t export:
local layer = sprite.layers[1]
layer:setReference(true)

if layer:isReference() then
  print("This layer is for reference only")
end

Collapsed Groups

Control whether layer groups are expanded or collapsed in the UI:
local group = sprite:newGroup()
group:setCollapsed(true)  -- Collapse in UI

print(group:isCollapsed())  -- true
print(group:isExpanded())   -- false

Layer Hierarchy

local layer = sprite.layers[1]

-- Sibling navigation
local prev = layer:getPrevious()  -- Previous sibling
local next = layer:getNext()      -- Next sibling

-- Hierarchy navigation
local prevAll = layer:getPreviousInWholeHierarchy()
local nextAll = layer:getNextInWholeHierarchy()

-- Check relationships
if layer:hasAncestor(someGroup) then
  print("Layer is inside someGroup")
end

Working with Groups

local sprite = Sprite(32, 32)

-- Create a group
local group = sprite:newGroup()
group.name = "Characters"

-- Add layers to group
local layer1 = sprite:newLayer()
layer1.parent = group

-- Access group's layers
for i, layer in ipairs(group.layers) do
  print(layer.name)
end

-- Count layers in group
print(#group.layers)

Working with Cels

Layers contain cels (cells) - the actual image data at specific frames.
local sprite = Sprite(32, 32)
local layer = sprite.layers[1]

-- Get cel at specific frame
local cel = layer:cel(1)  -- Frame 1
if cel then
  print(cel.image.width)   -- Access image data
  print(cel.position)      -- Cel position
end

-- Create new cel
sprite:newCel(layer, 2)  -- Create cel at frame 2

-- Get all cels from layer
local cels = {}
layer:getCels(cels)
print(#cels)  -- Number of cels in layer
A layer can have at most one cel per frame. Cels can be linked, meaning multiple frames share the same image data.

Layer Visibility

Hierarchy Visibility

A layer’s effective visibility depends on its entire parent chain:
local layer = sprite.layers[1]

-- Direct visibility
print(layer.isVisible)  -- Layer's own visibility flag

-- Effective visibility (includes parent visibility)
print(layer:isVisibleHierarchy())  -- true only if layer AND all parents are visible

-- Editable in hierarchy
print(layer:isEditableHierarchy())  -- true only if layer AND all parents are editable

-- Can edit pixels
print(layer:canEditPixels())  -- Combines visibility, editability, and layer type

Layer Operations

Creating Layers

local sprite = Sprite(32, 32)

-- Create new layer at top
local layer = sprite:newLayer()

-- Create layer group
local group = sprite:newGroup()

-- Delete layer
sprite:deleteLayer(layer)

Reordering Layers

-- Layers are stacked with the first layer at the bottom
local layer1 = sprite.layers[1]  -- Bottom
local layer2 = sprite.layers[2]  -- Above layer1

-- Move layers by changing parent relationships
-- or use the app commands for reordering

Layer Data

You can attach custom data to layers:
local layer = sprite.layers[1]

-- Store custom data
layer.data = "Character layer data"
print(layer.data)  -- "Character layer data"

-- Data persists when saving
sprite:saveAs("myfile.aseprite")

Layer UUIDs

Layers can have persistent UUIDs for identification:
local sprite = Sprite(32, 32)
local layer = sprite.layers[1]

-- Enable UUID usage for sprite
sprite.useLayerUuids = true

-- Get layer UUID
local uuid = layer.uuid
print(uuid)  -- Unique identifier

-- UUIDs persist across save/load when enabled
sprite:saveAs("test.aseprite")
UUIDs are useful for plugins that need to track specific layers across save/load cycles.

Best Practices

Use layer groups to organize complex artwork:
  • Characters
  • Background
  • Effects
  • UI Elements
This makes it easier to manage visibility and find specific layers.
Give layers descriptive names instead of using defaults. This makes it much easier to work with sprites that have many layers.
layer.name = "Player-Body"
layer.name = "Player-Eyes"
layer.name = "Background-Sky"
When working from reference images, place them in reference layers so they don’t export with your final artwork.
Set isEditable = false on layers you’ve finished to prevent accidental changes.

Common Patterns

Iterate All Layers

-- Get all layers (flattened hierarchy)
local allLayers = sprite:allLayers()
for i, layer in ipairs(allLayers) do
  print(i, layer.name)
end

-- Only visible layers
local visibleLayers = sprite:allVisibleLayers()

Find Specific Layer

function findLayerByName(sprite, name)
  for i, layer in ipairs(sprite:allLayers()) do
    if layer.name == name then
      return layer
    end
  end
  return nil
end

local layer = findLayerByName(sprite, "Character")

Clone Layer Structure

-- Duplicate a sprite to copy its layer structure
local original = Sprite(32, 32)
original:newLayer()
original:newGroup()

local copy = Sprite(original)  -- Copies all layers

Sprites

Learn about the sprite container

Frames

Understand animation frames and cels

Animation

Create animations using layers and frames

API Reference

For complete API documentation, see:

Build docs developers (and LLMs) love