This chapter teaches the structural organization of MicroSims that creates a consistent user experience. You will learn about the standard two-region architecture with a drawing region for visualizations and a control region for user interface elements. The chapter covers canvas dimension variables including canvasWidth, canvasHeight, drawHeight, and controlHeight, plus the use of margins for visual spacing. You will explore different layout patterns including standard, two-column, fixed, and responsive layouts.
Concepts Covered
This chapter covers the following 12 concepts from the learning graph:
You've learned to write code that works. Now it's time to make it shine.
Sometimes, to truly impress your students and colleagues, you need to add some spit and polish to your MicroSims. A simulation that looks professional—with clean layouts, consistent spacing, and thoughtful organization—commands attention and respect. It says, "This was crafted with care."
This chapter walks you through the architecture of a MicroSim and all the layout tricks that separate amateur-looking simulations from professional-quality educational tools. When you finish, your MicroSims won't just work—they'll look like a million bucks.
First Impressions Matter
Students make judgments about educational quality in seconds. A polished, well-organized MicroSim signals credibility and professionalism before a single interaction occurs.
MicroSim Architecture: The Blueprint
MicroSim architecture refers to the structural organization of your simulation—how the different parts are arranged and how they work together. Just as a building has a floor plan that organizes rooms, a MicroSim has an architecture that organizes visual and interactive elements.
The standard MicroSim architecture divides the canvas into two distinct regions:
Drawing Region: Where the simulation visualization lives
Control Region: Where sliders, buttons, and labels reside
This separation isn't arbitrary—it's based on user interface principles that make simulations intuitive and learnable.
<summary>MicroSim Architecture Diagram</summary>
Type: diagram
Purpose: Show the standard two-region MicroSim architecture with labeled dimensions (Bloom: Remember, Understand)
Canvas size: 400x450 pixels total
Components to show:
- Full canvas outline with label "canvasHeight = 450"
- Width dimension with label "canvasWidth = 400"
- Drawing region (top):
- Background: alice blue (#F0F8FF)
- Height label: "drawHeight = 400"
- Contains sample visualization (bouncing ball with trajectory)
- Margin lines shown as dashed (25px from edges)
- Label: "Drawing Region"
- Control region (bottom):
- Background: white (#FFFFFF)
- Height label: "controlHeight = 50"
- Contains sample slider and label
- Dividing line between regions (silver)
- Label: "Control Region"
- Margin annotations:
- Arrows showing 25px margins on left, right, top
- Label: "margin = 25"
Visual style:
- Clean, technical diagram style
- Dimension lines with arrows
- Dashed lines for margins
- Color-coded regions
Annotations:
- "Visualization goes here" in drawing region
- "User controls here" in control region
- Formula: "canvasHeight = drawHeight + controlHeight"
Color scheme:
- Drawing region: alice blue (#F0F8FF)
- Control region: white (#FFFFFF)
- Dimension lines: dark gray (#333)
- Margin lines: dashed light gray
Implementation: Static diagram or simple p5.js visualization
The Drawing Region: Your Visualization Canvas
The drawing region is the primary visual area where your simulation's main content appears. This is where balls bounce, pendulums swing, graphs plot, and physics happens.
Characteristics of the Drawing Region
Occupies the upper portion of the canvas
Uses a consistent background color (typically alice blue: rgb(240, 248, 255))
Contains all animated or interactive visualizations
Respects margins to prevent elements from touching edges
Height is defined by the drawHeight variable
Drawing Region Best Practices
Keep it focused: One main visualization, not multiple competing elements
Respect boundaries: Elements should stay within margin boundaries
Use the full space: Don't leave large empty areas unused
Consistent background: Alice blue provides gentle contrast without distraction
Clear visual hierarchy: Most important elements should be most prominent
1 2 3 4 5 6 7 8 9101112
// Drawing region setupletdrawHeight=400;functiondraw(){// Clear drawing region with alice bluefill(240,248,255);noStroke();rect(0,0,width,drawHeight);// Your visualization code goes here// ...}
The Control Region: Command Central
The control region is the dedicated area for user interface elements—sliders, buttons, labels, and value displays. Separating controls from the visualization prevents clutter and creates a predictable user experience.
Characteristics of the Control Region
Located at the bottom of the canvas
Uses a white background for clean contrast
Contains sliders, buttons, and text labels
Height is defined by the controlHeight variable (typically 50-100 pixels)
Has a subtle dividing line separating it from the drawing region
Control Region Layout
A well-organized control region follows this pattern:
1
| Label: |===========O===========| Value |
Where:
- Label appears to the left of the slider
- Slider occupies the middle space
- Value displays to the right (updates dynamically)
// Control region setupletcontrolHeight=50;letsliderLeftMargin=100;functiondraw(){// Draw control region backgroundfill(255);noStroke();rect(0,drawHeight,width,controlHeight);// Dividing linestroke(200);strokeWeight(1);line(0,drawHeight,width,drawHeight);// Labelfill(0);noStroke();textAlign(LEFT,CENTER);textSize(14);text("Speed:",10,drawHeight+controlHeight/2);// Value displaytextAlign(RIGHT,CENTER);text(speedSlider.value().toFixed(1),width-10,drawHeight+controlHeight/2);}
Canvas Dimension Variables
Professional MicroSims use named variables for all dimensions rather than magic numbers. This makes code readable, maintainable, and easy to modify.
The second version tells a story: the rectangle is the control region, the circle is centered in the drawing area, and the text is positioned in the control region.
The Margin Variable: Breathing Room
The margin variable defines the spacing between content and canvas edges. Margins create visual breathing room that makes simulations feel polished rather than cramped.
Why Margins Matter
Without Margins
With Margins
Elements touch edges
Clean visual boundaries
Feels cramped
Feels spacious
Text may be cut off
All content visible
Amateur appearance
Professional appearance
Using Margins Consistently
Apply margins to:
Title positioning: text(title, canvasWidth/2, margin)
Shape boundaries: if (x < margin || x > canvasWidth - margin)
Label placement: text(label, margin, y)
Drawing constraints: Keep visualizations within margin boundaries
1 2 3 4 5 6 7 8 9101112
letmargin=25;functiondraw(){// Title with margin from toptextAlign(CENTER,TOP);text("Bouncing Ball Simulation",canvasWidth/2,margin);// Ball constrained by marginsif(ballX<margin+ballRadius||ballX>canvasWidth-margin-ballRadius){velocityX*=-1;// Bounce off margin boundaries}}
<summary>Interactive Margin Visualization</summary>
Type: microsim
Learning objective: Help students visualize how margins create visual boundaries and affect element positioning (Bloom: Understand, Apply)
Canvas layout:
- Drawing area: 400x350 pixels
- Control area: 50 pixels
Visual elements:
- Canvas outline (dark gray)
- Margin boundary rectangle (dashed red line, inset by margin value)
- Sample elements positioned at margin boundaries:
- Title text at top margin
- Shapes bouncing within margin boundaries
- Labels positioned at left margin
- Dimension annotations showing margin distances
- "Safe zone" label in center
- "Margin zone" labels in edge areas
Interactive controls:
- Slider: "Margin Size" (0-50 pixels, default 25)
- As slider changes, margin boundary updates in real-time
- Sample elements reposition to respect new margins
Behavior:
- Changing margin slider updates dashed boundary line
- Bouncing shape adjusts its boundaries
- Shows how larger margins create more breathing room
- Demonstrates margin = 0 vs margin = 50 difference
Color scheme:
- Drawing area: alice blue
- Margin boundary: dashed red
- Safe zone: light green tint
- Edge zones: light red tint
Implementation: p5.js with slider control
The Standard Layout: Your Default Choice
The standard layout is the go-to pattern for most MicroSims. It features a single drawing region above a control region, with all elements arranged vertically.
Standard Layout Structure
1 2 3 4 5 6 7 8 9101112
┌─────────────────────────────────┐
│ │
│ Drawing Region │
│ (Visualization Area) │
│ │
│ drawHeight │
│ │
├─────────────────────────────────┤
│ Label: ════════O════════ Value │
│ Control Region │
│ controlHeight │
└─────────────────────────────────┘
// Standard Layout TemplateletcanvasWidth=400;letdrawHeight=350;letcontrolHeight=50;letcanvasHeight=drawHeight+controlHeight;letmargin=25;letspeedSlider;functionsetup(){constcanvas=createCanvas(canvasWidth,canvasHeight);canvas.parent(document.querySelector('main'));// Create slider in control regionspeedSlider=createSlider(1,10,5);speedSlider.position(100,drawHeight+15);speedSlider.size(canvasWidth-150);describe('Standard layout MicroSim with visualization and controls');}functiondraw(){// Drawing regionbackground(240,248,255);// Control regionfill(255);noStroke();rect(0,drawHeight,canvasWidth,controlHeight);// Dividing linestroke(200);line(0,drawHeight,canvasWidth,drawHeight);// Control labelfill(0);noStroke();textSize(14);textAlign(LEFT,CENTER);text("Speed:",10,drawHeight+controlHeight/2);// Value displaytextAlign(RIGHT,CENTER);text(speedSlider.value(),canvasWidth-10,drawHeight+controlHeight/2);// Your visualization here...}
The Two-Column Layout: Side-by-Side Power
The two-column layout splits the drawing region into two side-by-side areas. This is perfect for simulations that need to show two related views simultaneously—like a main visualization paired with a graph or a comparison view.
Two-Column Layout Structure
1 2 3 4 5 6 7 8 910
┌────────────────┬────────────────┐
│ │ │
│ Left │ Right │
│ Column │ Column │
│ (Simulation) │ (Graph) │
│ │ │
├────────────────┴────────────────┤
│ Label: ════════O════════ Value │
│ Control Region │
└─────────────────────────────────┘
// Two-Column Layout TemplateletcanvasWidth=600;letdrawHeight=350;letcontrolHeight=50;letcanvasHeight=drawHeight+controlHeight;letmargin=25;// Column dimensionsletleftColumnWidth,rightColumnWidth;functionsetup(){constcanvas=createCanvas(canvasWidth,canvasHeight);canvas.parent(document.querySelector('main'));// Calculate column widthsleftColumnWidth=canvasWidth/2;rightColumnWidth=canvasWidth/2;describe('Two-column layout with simulation and graph');}functiondraw(){// Left column - Simulationfill(240,248,255);noStroke();rect(0,0,leftColumnWidth,drawHeight);// Right column - Graph (slightly different tint)fill(248,248,255);rect(leftColumnWidth,0,rightColumnWidth,drawHeight);// Column dividerstroke(200);strokeWeight(1);line(leftColumnWidth,0,leftColumnWidth,drawHeight);// Control regionfill(255);noStroke();rect(0,drawHeight,canvasWidth,controlHeight);// Use push/translate/pop for each columnpush();translate(0,0);drawSimulation();// Draw in left column coordinatespop();push();translate(leftColumnWidth,0);drawGraph();// Draw in right column coordinatespop();}
The Push/Translate/Pop Pattern
For two-column layouts, use push(), translate(), and pop() to work in local coordinates:
1 2 3 4 5 6 7 8 9101112
functiondrawGraph(){// Now (0,0) is the top-left of the right column// All drawing happens relative to this origin// Draw axesstroke(0);line(margin,drawHeight-margin,rightColumnWidth-margin,drawHeight-margin);line(margin,margin,margin,drawHeight-margin);// Plot data// coordinates are relative to column, not canvas}
<summary>Two-Column Layout Interactive Demo</summary>
Type: microsim
Learning objective: Demonstrate how two-column layouts work with synchronized visualizations (Bloom: Understand, Apply)
Canvas layout:
- Total width: 600 pixels
- Draw height: 350 pixels
- Control height: 50 pixels
Visual elements:
Left column (300px wide):
- Bouncing ball simulation
- Ball moves within left column boundaries
- Background: alice blue
Right column (300px wide):
- Real-time graph showing ball's Y position over time
- X-axis: time (scrolling)
- Y-axis: vertical position
- Line graph updating each frame
- Background: slightly different blue tint
Divider:
- 1px silver line between columns
Interactive controls:
- Slider: "Gravity" (affects ball in left column, shows in graph on right)
- Slider: "Ball Size"
Behavior:
- Ball bounces in left column
- Graph in right column plots ball's Y position over time
- Changing gravity affects both visualizations
- Demonstrates data flow between columns
Educational emphasis:
- Shows how columns can display related information
- Demonstrates push/translate/pop coordinate system
- Shows real-time data visualization
Implementation: p5.js with push/translate/pop pattern
Fixed Layout: Predictable and Stable
A fixed layout maintains constant dimensions regardless of the browser window or container size. The canvas is always the same width and height, providing a completely predictable visual experience.
Characteristics of Fixed Layout
Aspect
Fixed Layout Behavior
Canvas size
Always the same (e.g., 400x450)
Responsiveness
None—doesn't adapt to container
Predictability
Complete—elements never move
Best for
Precise positioning, print layouts
Drawbacks
May not fit all containers
When to Use Fixed Layout
When precise pixel positioning is critical
For simulations embedded in fixed-width containers
When responsive adaptation would break the visualization
For print or PDF export
For consistent screenshots and documentation
Fixed Layout Implementation
1 2 3 4 5 6 7 8 910111213141516
// Fixed Layout - No responsive functions neededletcanvasWidth=400;// Always 400 pixelsletdrawHeight=350;letcontrolHeight=50;letcanvasHeight=drawHeight+controlHeight;functionsetup(){createCanvas(canvasWidth,canvasHeight);// Fixed size// No windowResized() function// No updateCanvasSize() function}functiondraw(){// Layout never changes// All positions are constant}
Responsive Layout: Adapting with Grace
A responsive layout adjusts to the available container width, making your MicroSim work beautifully on any screen size—from narrow mobile devices to wide desktop monitors.
Characteristics of Responsive Layout
Aspect
Responsive Layout Behavior
Canvas width
Adapts to container width
Canvas height
Usually fixed (drawHeight + controlHeight)
Elements
Reposition relative to width
Best for
Web embedding, intelligent textbooks
Requires
windowResized() and updateCanvasSize()
The Responsive Pattern
Responsive layouts require three key elements:
Initial size detection in setup()
windowResized() function to detect changes
updateCanvasSize() function to recalculate dimensions
// Responsive Layout TemplateletcanvasWidth=400;// Initial/minimum widthletdrawHeight=350;// Fixed heightletcontrolHeight=50;letcanvasHeight=drawHeight+controlHeight;letmargin=25;functionsetup(){updateCanvasSize();// Get initial container widthconstcanvas=createCanvas(canvasWidth,canvasHeight);canvas.parent(document.querySelector('main'));describe('Responsive MicroSim that adapts to container width');}functionwindowResized(){updateCanvasSize();resizeCanvas(canvasWidth,canvasHeight);repositionControls();// Reposition sliders, buttons}functionupdateCanvasSize(){// Get container width, with minimumconstcontainer=document.querySelector('main');canvasWidth=max(300,container.offsetWidth);// Minimum 300px// canvasHeight stays fixed}functionrepositionControls(){// Update slider positions and sizesspeedSlider.position(100,drawHeight+15);speedSlider.size(canvasWidth-150);}functiondraw(){// Use canvasWidth for all horizontal positioning// Elements automatically adapt when width changes}
// Professional MicroSim Template// Demonstrates: architecture, regions, dimensions, responsive layout// Canvas dimensionsletcanvasWidth=400;letdrawHeight=350;letcontrolHeight=75;// Extra height for two rows of controlsletcanvasHeight=drawHeight+controlHeight;letmargin=25;letsliderLeftMargin=100;// Simulation variablesletball={x:200,y:175,vx:3,vy:2};letspeedSlider,sizeSlider;functionsetup(){updateCanvasSize();constcanvas=createCanvas(canvasWidth,canvasHeight);canvas.parent(document.querySelector('main'));// Create controlsspeedSlider=createSlider(1,10,5,0.5);sizeSlider=createSlider(10,50,25,1);repositionControls();describe('Bouncing ball with speed and size controls, responsive layout');}functionupdateCanvasSize(){constcontainer=document.querySelector('main');if(container){canvasWidth=max(300,container.offsetWidth);}canvasHeight=drawHeight+controlHeight;}functionwindowResized(){updateCanvasSize();resizeCanvas(canvasWidth,canvasHeight);repositionControls();}functionrepositionControls(){constsliderWidth=canvasWidth-sliderLeftMargin-60;speedSlider.position(sliderLeftMargin,drawHeight+12);speedSlider.size(sliderWidth);sizeSlider.position(sliderLeftMargin,drawHeight+42);sizeSlider.size(sliderWidth);}functiondraw(){// === DRAWING REGION ===background(240,248,255);// Alice blue// Update physicsletspeed=speedSlider.value();ball.x+=ball.vx*speed*0.2;ball.y+=ball.vy*speed*0.2;// Bounce off marginsletradius=sizeSlider.value()/2;if(ball.x<margin+radius||ball.x>canvasWidth-margin-radius){ball.vx*=-1;ball.x=constrain(ball.x,margin+radius,canvasWidth-margin-radius);}if(ball.y<margin+radius||ball.y>drawHeight-margin-radius){ball.vy*=-1;ball.y=constrain(ball.y,margin+radius,drawHeight-margin-radius);}// Draw ballfill(100,150,255);stroke(50,100,200);strokeWeight(2);circle(ball.x,ball.y,sizeSlider.value());// === CONTROL REGION ===fill(255);noStroke();rect(0,drawHeight,canvasWidth,controlHeight);// Dividerstroke(220);strokeWeight(1);line(0,drawHeight,canvasWidth,drawHeight);// Labels and valuesfill(60);noStroke();textSize(14);textAlign(LEFT,CENTER);// Speed controltext("Speed:",margin,drawHeight+25);textAlign(RIGHT,CENTER);text(speedSlider.value().toFixed(1),canvasWidth-margin,drawHeight+25);// Size controltextAlign(LEFT,CENTER);text("Size:",margin,drawHeight+55);textAlign(RIGHT,CENTER);text(sizeSlider.value()+"px",canvasWidth-margin,drawHeight+55);}
Key Takeaways
You now have the knowledge to make your MicroSims look like a million bucks:
MicroSim Architecture divides the canvas into a drawing region and control region for clarity.
The Drawing Region hosts your visualization with a consistent alice blue background.
The Control Region provides a clean white space for sliders, buttons, and labels.
Use named dimension variables (canvasWidth, drawHeight, controlHeight, canvasHeight) for readable, maintainable code.
The margin variable creates breathing room that separates amateur layouts from professional ones.
The Standard Layout is your default—simple, clean, effective.
Use Two-Column Layout when you need side-by-side visualization and data display.
Fixed Layout offers complete predictability at the cost of adaptability.
Responsive Layout adapts gracefully to any container width using windowResized() and updateCanvasSize().
The push/translate/pop pattern enables working in local coordinates for multi-column layouts.
Sliders must be repositioned when the canvas resizes—don't forget repositionControls()!
Professional polish comes from consistent spacing, proper alignment, and attention to detail.
Challenge: Identify the layout type
Look at three MicroSims on the gallery page. For each one, identify whether it uses Standard, Two-Column, Fixed, or Responsive layout. What clues helped you determine the layout type?
Next Steps
Your MicroSims now have professional architecture and layout. In the next chapter, we'll add interactive controls—sliders, buttons, and more—that bring your simulations to life and let users explore parameters hands-on.
Remember: the difference between good and great is in the details. Take time to polish your layouts, and your simulations will command the respect they deserve.