Skip to content
NovaSpark Docs v1.0.0
Live Demo Support

Build

Mascot

An animated character that follows the pointer and changes expression with what the visitor does.

Mascot gives your site a small character with a face: a chatbot’s avatar, a guide beside a form, a personality in a hero. Its eyes follow the pointer, it blinks and floats on its own, and it reacts when something happens — thinking while a form sends, pleased when it has gone, bored by an empty one, asleep when nobody is around. It can also talk, wave, say a few words in a bubble and float in a corner as a chat launcher.

You choose its body and eyes, decide what it can look like, and write simple rules for when it looks that way. No code is needed, and it works straight away on the default settings. If you do write code, see For developers.

Quick start #

  1. Add the widgetSearch for Mascot in the Elementor panel and drag it onto the page.
  2. Pick a bodyUnder Character, click one of the shape tiles. The face moves to suit it.
  3. Set its colours and sizeUnder Style → Mascot.
  4. Try itOpen the page or Elementor’s Preview. Move the pointer, click the mascot four times, then leave the pointer still for five seconds.

Triggers only run on the live page and in Preview. On the editor canvas the mascot keeps moving, so you can place it, but it holds one expression. Use Preview Expression under Character to see the others there.

Body and eyes #

Body offers 26 ready-made shapes, from the Ghost to a Chat bubble, a Cloud and a Star. Each one comes with a face position that suits it, so you can switch freely.

SettingDefaultWhat it does
BodyGhostA shape tile, or Custom SVG to upload your own
Eyes X, Eyes YEmptyWhere the face sits, from 0 to 100% of the body. Empty uses the position that suits the chosen body
Eyes SizeEmptyThe face’s width as a share of the body’s. Empty works the same way
Show MouthOffGives it a mouth. See Mouth and talking
Hold ExpressionNoneShows one expression at all times and turns the Triggers off
Preview ExpressionDefaultEditor only: which expression the canvas shows
Accessible NameEmptyWhat a screen reader announces. Leave it empty if the mascot is decoration
Mascot IDEmptyLets custom code talk to this mascot alone

Using your own SVG

Bodies, eyes and mouths can all be your own artwork. A few rules decide how well a drawing animates:

Filled shapes onlyOutline any strokes in your design tool before exporting. A stroke with no fill does not show.
A body in one shapeOne filled shape gets the wave along its bottom edge. A body of several shapes still works, but moves as one piece.
Eyes as separate shapesEach eye is its own shape, drawn on the same artboard size in every expression, so the face stays in place when it changes.
The same number of eyesSolid eyes morph smoothly into each other. A different number of eyes, or a hollow ring, swaps during a quick blink instead.

An SVG that cannot be read is not shown. A custom body falls back to the bundled one; an expression is left out, along with any trigger that points at it.

Expressions #

The Expressions list is everything the mascot can look like. Change a row to restyle an expression, or add a row to create a new one. Each row has:

NameTriggers pick expressions by this name.
EyesOne of the eight bundled pairs, or Custom SVG.
MouthMatch Eyes, None, one of the eight bundled mouths, or Custom SVG. Shows once Show Mouth is on.
TalksThe mouth keeps moving for as long as this expression shows.
Talk While SpeakingUse The General Setting, On or Off — overrides Character → Talk While Speaking for this expression only. See Speech bubble.
HandsNone, or a pose. See Hands.
EffectNone, or something floating around the head. See Effects.
BlinksTurn off for eyes that already look closed.
ReactionNone, Head Shake, Hop or Happy Jump (four hops, leaning right and left), played as the expression starts.
Body ColourKeep, Solid or Gradient. The colour fades in with the expression and out after it, with a separate dark mode value.

Out of the box, Normal, Focus, Confuse, Thinking and Shy blink. Happy hops, Upset shakes its head, steams and turns orange and red, and Sleepy shows Floating Zzz. Thinking shows a thought bubble, Shy covers its eyes, and Hello waves.

A row saved before these settings existed keeps working as it was, including one with the old Floating Zzz switch on.

Renaming an expression? Triggers remember it by name, so check the rows that use it and pick it again.

Triggers #

Each row says: Show this expression When this is true. The top row whose condition is true wins, so drag the rows to set the priority, and keep Otherwise (Default) last.

WhenIt happens whenYou also set
Pointer Over ElementThe pointer is inside something on the pageElement
Focus In ElementThe keyboard focus is inside itElement
Click Or Submit On ElementIt is clicked, or a form inside it is submittedElement, Only If Empty
Typing In FieldEach keystroke. Clicking into the field does not countField
Field EmptiedA field that had text becomes emptyField
Form SendingA form is on its way. Only for forms that stay on the pageElement (optional)
Form SentA form was sentElement (optional)
Form InvalidA form was refused because fields are missing or wrongElement (optional)
Form FailedA form could not be sentElement (optional)
Pointer Over MascotThe pointer is on the mascot’s body—
Clicks On MascotThat many clicks within two secondsClicks
Comes Into ViewThe first time it is on screen, which for a mascot near the top means on page load—
No ActivityNo pointer, key or scroll for that longSeconds
Pointer Leaves PageThe pointer moves out of the window—
At RandomAbout that often, and only while the Default row is showingSeconds
Otherwise (Default)Always. It is what the mascot falls back to—

Element and Field are CSS selectors, such as #contact or .my-class. To give something an ID, select it and set CSS ID in its Advanced tab.

Every row can also say something. A new mascot starts with these rows, so it reacts to a form and greets the visitor with nothing to set up:

ShowWhenSetting
HappyForm Sent—
SadForm Failed—
BoredForm Invalid—
ThinkingForm Sending—
ShyFocus In Elementinput[type="password"]
UpsetClicks On Mascot4 clicks
HelloComes Into View—
HappyPointer Over Mascot—
SadPointer Leaves Page—
SleepyNo Activity5 seconds
ConfuseAt RandomAbout every 12 seconds
NormalOtherwise (Default)—

Holding an expression

There are two ways, and they do different jobs:

Hold For, on a Trigger rowKeeps the expression for that many seconds after the row stops being true. Without it, a click would show for a single moment.
Hold Expression, under CharacterPins one expression for good and turns every Trigger off. Useful for a mascot that is purely decoration.

Linking it to your page #

Form results work with Contact Form 7, the NovaKit Newsletter form and NovaKit Custom forms. Accounts forms are not covered. Form Invalid also fires when a browser refuses an empty Required field. See Forms for setting these up. On a mascot added before these became the defaults, add these rows above the Default row:

ShowWhenSetting
HappyForm SentHold For 3
BoredForm InvalidHold For 2
SadForm FailedHold For 3
FocusTyping In FieldField: .wpcf7 textarea

With two forms on a page, put a selector for the one you mean in Element. Left empty, a form row listens to every form.

For a real chat box, follow Connect a chatbot. For a Send button of your own that is not a NovaKit Form: one button can do two different things. Order matters here: the first row that accepts the click takes it, so the empty case goes on top. Say the field’s ID is message and the button’s is send:

ShowWhenSetting
BoredClick Or Submit On ElementElement: #send
Only If Empty: #message
HappyClick Or Submit On ElementElement: #send
SadField EmptiedField: #message
FocusTyping In FieldField: #message

Several on one page

Add as many as you need. Each has its own body, expressions and rules, and they do not interfere with each other. A mascot scrolled out of view stops moving until it returns.

Mouth and talking #

Turn on Show Mouth under Character. Every expression then picks a mouth that matches its eyes, and you can change any of them on its row. The mouth rides the same head as the eyes and morphs between shapes.

SettingDefaultWhat it does
Talk While SpeakingOnThe mouth moves while a Say bubble shows words. Turn off to keep it still. Any expression row can override this — see Expressions
Mouth X, Mouth YEmptyWhere it sits, as a percentage of the body. Empty places it under the eyes
Mouth SizeEmptyIts artboard’s width as a share of the body’s. Empty is 70% of the Eyes Size
Mouth ColourEmptyUnder Style → Mascot, with a dark mode value. Empty uses the Eyes Colour

It talks while a speech bubble’s words appear, on any expression with Talks on, and when code asks it to. Each mouth talks in character: a smile opens into an open smile, a frown into an open frown, and Bored just mumbles. The Sleepy mouth snores: it swells and shrinks slowly for as long as it shows. Draw your own mouths like the eyes: filled shapes on a 120 by 50 artboard.

A Say bubble moves the mouth too, unless Talk While Speaking is off — either the general one here, or an expression row’s own override. The mouth then stays as it is while the bubble shows its words.

Hands #

Two floating hands with no arms, so they suit every body and sit against its own outline. Each expression picks a pose under Hands:

WaveOne hand up, waving
Thumbs UpOne hand beside the body
CheerBoth up, bobbing
ShrugBoth out to the sides, palms up
Cover EyesBoth over the eyes, staying on them as the head turns, and now and then peeking. Shy uses it, on a password field
Point At PointerOne hand, following the pointer around the body

Hands Colour is under Style → Mascot. Left empty, it is a tint between the Body and Eyes Colours, which reads against the page and in front of the body.

Effects #

Effect on an expression row floats something around the head for as long as that expression shows, then clears it away:

Floating ZzzZ’s rise from the upper right
Thinking DotsThree dots bounce inside a thought bubble, and the mascot looks up towards it. The bubble takes the effect colour and the dots take the Eyes Colour
Hearts, SparklesRise, or twinkle, around the head
Question Mark, Exclamation MarkPops up beside the head
Sweat DropSlides down from the upper left
SteamPuffs out of both sides

Style → Floating Effects has Position X and Y, as a percentage of the body and set per device, and a Colour with a dark mode value. Left empty, effects use the Body Colour.

Speech bubble #

Type in Say on any Trigger row and the words appear in a bubble as that row starts, with the mouth moving. Put several lines and choose their Order: Random (the default) never repeats the same line twice running; In Order goes through them one by one and starts again at the top. Turn on Say Once for a greeting that should not repeat on the same page view. A bubble stays long enough to read, then leaves by itself.

Its look is under Style → Speech Bubble: which side it sits on, Max Width, Typography, colours with dark mode values, Padding, Corner Radius and Box Shadow. Preview In Editor shows a sample to style by. If the chosen side would run off the screen, it moves to one that fits.

Right-to-left languages work by themselves. Each message sets its own direction from its first letters, so Arabic or Hebrew reads right to left even on a left-to-right site, and English reads left to right on a right-to-left one. There is nothing to set, and one row can mix languages across its lines. Choose a font with those letters under Typography if your site’s font lacks them.

Link and floating launcher #

Link And Position turns the mascot into something to click.

SettingDefaultWhat it does
LinkEmptyWhere a press on its body or bubble goes. Set Accessible Name too, as that names the link
PositionIn The PageFloating, Bottom End or Bottom Start pins it to a corner of the screen, and it pops in on arrival
Offset From Side, From BottomEmptyThe distance from the corner, per device. Empty is 1.5rem
Z-IndexEmptyWhat it sits above. Empty is 290, above the page and under popups, so a popup it opens covers it

It floats on the live page and in Preview. In the editor it stays in place so you can select it. To show it on every page, put it in a footer Global Block.

Open a popup from it

  1. Build the popupA Popup Global Block holding your chat form. Check that its Display Conditions include this page. With none set, it is on every page.
  2. Set the LinkUnder Link And Position, press the dynamic tags icon on Link and choose NovaKit Trigger Link.
  3. Point it at the popupSet Action to Open, Target Type to Popup, then pick yours under Popup.
  4. Name itSet Accessible Name under Character, such as “Open chat”.

Not on an Elementor Canvas page. That template skips the theme’s header, which is where popups are added to the page, so the mascot has nothing to open. Use any other page template.

On a phone

There is no separate setup. It works by touch, and a bubble that would run off the screen moves to fit. These are worth setting with Elementor’s phone view selected:

Size, under Style → MascotThe 124px default is large for a corner. About 64px suits a phone
Offset From Side, From BottomLift it clear of anything fixed at the bottom of your page, such as a cookie banner
Max Width, under Style → Speech BubbleLower it if a bubble crowds the screen

To leave a mascot off phones altogether, use Advanced → Responsive.

Motion and style #

The defaults under Motion are tuned to feel calm, so change them one at a time.

SettingDefaultWhat it does
Follow PointerOnEyes, head and body turn towards the pointer
Head Turn24How far the face turns
Body Lean7How far the body tilts
Follow Speed1How quickly it catches up
Bounce0.55How much it overshoots and settles
Wave3.5The ripple along the bottom edge. Set 0 for a rigid shape, such as a Square
Wave Starts At (%)68How far down the body the ripple begins
Float3.5The gentle drift up and down
Blink And GlancesOnBlinks and looks around on its own
Idle AnticsOnNow and then, a head spin, a look around or a hop
Antics Every (s)10Roughly how often

Style → Mascot has Size (124px by default), Alignment, Body Colour and Eyes Colour, each colour with a dark mode value.

Check your eye colour against every body colour. If an expression changes the body colour, the eyes must stay readable on it too, and in dark mode as well.

Accessibility and devices #

Screen readersWith no Accessible Name the mascot is hidden from them. With one, it reads as an image of that name. Expression changes are not announced, so never rely on the mascot alone to report something, such as a form error.
Reduced motionFor visitors who ask their device for less motion, it stays still and expressions change at once. Effects and hands stand still, the Sleepy mouth does not snore, and a bubble simply appears.
Speech bubbleScreen readers announce its words as a status message.
Touch screensThere is no pointer to follow, so it does not follow. Everything else still works.

For developers #

To connect a chatbot, start with Connect a chatbot, which needs less code than this. The panel covers anything a selector can reach. For everything else — a reply arriving, a game score — there is an event and a set of CSS hooks. Add the code the way you add any other: see Custom CSS and JS.

Driving it from JavaScript

Dispatch nk:mascot on document:

your-script.js
document.dispatchEvent( new CustomEvent( 'nk:mascot', { detail: {
    expression: 'happy',  // A row's name as a slug. null lets the Triggers run again.
    hold: 3,              // Seconds, or true for until told otherwise. Default 2.5.
    mascot: 'helper',     // Optional Mascot ID. Without it, every mascot on the page.
    say: 'On it!',        // Words in the bubble. hold applies. null takes them away.
    talk: true,            // The mouth moves: true, false, or seconds.
} } ) );
The slugThe row’s Name in lower case, with anything else turned into hyphens: Cheeky Wink becomes cheeky-wink. A slug no row has is ignored.
PriorityThe event beats every Trigger until its hold ends. Only Hold Expression beats the event.
Each is optionalSend only say or talk and the expression stays as it is. say without hold stays long enough to read.
AfterwardsWhen the hold ends the Triggers take over again, so there is nothing to clean up. The exception is hold: true, which needs expression: null.

For example, a mascot that waits on a reply from something that is not a NovaKit Form:

your-script.js
const mascot = ( expression, hold ) => document.dispatchEvent(
    new CustomEvent( 'nk:mascot', { detail: { expression, hold, mascot: 'helper' } } )
);

mascot( 'focus', true );          // Stay on Focus while the reply is on its way.

fetch( '/my-chat-endpoint' )
    .then( () => mascot( 'happy', 3 ) )
    .catch( () => mascot( 'sad', 3 ) );

Reporting your own form’s result

A form that NovaKit does not know about can still fire the Form rows. Dispatch one of these from the form element, with bubbles: true so the mascot hears it and the row’s Element can match:

your-script.js
form.dispatchEvent( new CustomEvent( 'nk-form:submit', { bubbles: true } ) );  // Form Sending starts
form.dispatchEvent( new CustomEvent( 'nk-form:success', { bubbles: true } ) ); // Form Sent
form.dispatchEvent( new CustomEvent( 'nk-form:error', { bubbles: true } ) );   // Form Failed
form.dispatchEvent( new CustomEvent( 'nk-form:invalid', { bubbles: true } ) ); // Form Invalid
form.dispatchEvent( new CustomEvent( 'nk-form:done', { bubbles: true } ) );    // Form Sending ends

Contact Form 7’s own events are already heard: wpcf7beforesubmit starts Form Sending and wpcf7submit ends it, wpcf7mailsent counts as Form Sent, wpcf7invalid as Form Invalid, and wpcf7mailfailed and wpcf7spam as Form Failed.

Styling it from CSS

The current expression is always on the root element as data-nk-mascot-state, so CSS or a script can respond to it. These custom properties drive the look:

PropertyControls
--nk-mascot-sizeThe width, with a unit
--nk-mascot-bodyThe body colour
--nk-mascot-eyesThe eye colour
--nk-mascot-mouthThe mouth colour. Falls back to the eye colour
--nk-mascot-handsThe hands’ colour. Falls back to a tint of the body and eyes
--nk-mascot-bubble-bg, -bubble-textThe speech bubble’s colours
--nk-mascot-zzzThe effects’ colour. Falls back to the body colour
--nk-mascot-eye-x, -eye-y, -eye-sizeThe face position, as plain numbers meaning percent
--nk-mascot-mouth-x, -mouth-sizeThe mouth’s position and size, the same way
--nk-mascot-zzz-x, -zzz-yThe effects’ offset, as plain numbers meaning percent
novaspark-child/style.css
/* Pink eyes while it is upset. */
.nk-mascot[data-nk-mascot-state="upset"] {
    --nk-mascot-eyes: #ffc2d1 !important;
}

Why !important? A value set in the panel is written with a very specific selector, and Body Colour and Eyes Colour always have one. A property the panel has left empty, such as --nk-mascot-zzz, can be set with an ordinary rule.

Esc