[Studio Beta] Styling Transitions


Hi Creators!

We’re excited to announce Styling Transitions, a performant, scalable, and seamless way to add polish and motion to your interfaces. Transitions allow you to define how property values tween over a set duration directly in Stylesheets, moving your UI logic into a clean, no-code declarative workflow. You can use Transitions to build buttons that gently pop when hovered, frames that slide out to reveal extra content, cards that rotate slightly when pressed, and more!

What’s Included?

  • :gear: Full Range of Capabilities: Support for TweenInfo parameters, including duration, easing styles (like Elastic or Cubic), easing directions, and start delays.

  • :sparkles: Seamless Styling Integration: Automatically animate changes to any styleable property like BackgroundColor3, Size, or Rotation when an element’s style changes.

  • :bullseye: Input-Based Motion: Easily create high-fidelity hover and pressed states by defining transitions that trigger automatically when a user interacts with your UI.

  • :wrench: Edit-time Preview: Transitions are evaluated by the Style Engine at edit-time in Studio, allowing real-time preview of UI animation for the first time while authoring!

Keep reading for more details on how to try these out :slightly_smiling_face:


How to Enable the Beta

  1. Navigate to File > Beta Features.
  2. Find and check the box for Styling Transitions.
  3. Restart Roblox Studio when prompted.

What are Styling Transitions?

Styling Transitions are a way to set up simple tween effects that automatically occur when the styles applied to an instance are changed. A Transition is defined using the same properties you’re already familiar with if you’ve used TweenService:

  • Duration: The total length of the animation in seconds, which defines how long it takes to get from Point A to Point B. A low duration makes the UI feel snappy, while a high duration makes the UI feel more cinematic.
  • EasingStyle: The curve of movement that controls the acceleration and deceleration of the change. Check out the linked documentation to read more about different styles.
  • EasingDirection: Determines which end of the transition the Easing Style is applied to: the start (In), the end (Out), or both (InOut).
  • Delay: A “wait period” in seconds. The property won’t start changing until this amount of time has passed after the trigger.

You can either define Transitions explicitly per-property, or you can set a “Default Transition” that applies to all properties. If both are set within the same hierarchy, the per-property Transition(s) will take precedence over the Default Transition.

Building Higher-Fidelity UI with Transitions

Adding simple Transitions automatically elevates your UI, and they’re easy to start integrating into your StyleSheets! Everything shown below is embedded within this sample file, which has more examples for you to explore: StylingTransitionsDemo.rbxl

You can implement Transitions using either the Style Editor for a no-code workflow or through Luau scripts for more dynamic control.

Using the Style Editor

Adding Transitions in the Style Editor works like adding any other styled property. (Friendly plug – if you want to learn more about other Style Editor workflows, check out this documentation.)

Let’s walk through how to create a simple hover transition.

  1. Select the UI element in the Style Editor – here, we’re using TextButton.
  2. Add the properties you want on the default button – below, we’ve added a FontFace, Size, and TextSize.
  3. Underneath the TextButton, add a Hover GuiState. Under Hover, add the properties you want when the hover state is active – below, we’ve changed the BackgroundColor3, Size, and TextColor.
  4. Next to the Hover row, click on the three dots, then Insert > Transition. This transition applies when a player enters Hover.
  5. Configure your Tween parameters: Set your duration, easing style, and delay.
  6. Add a Default Transition to TextButton (using Insert > Transition like above), which transitions all properties back to their original values when exiting the Hover state.

Your Style Editor should look like this once you’ve completed the above steps:

To test out your new transition, add a ScreenGui in your DataModel, put some TextButtons inside, and add the StyleLink to this StyleSheet. At edit-time, when you hover over the buttons, you’ll see something like this!

Using Luau Scripts

For those who prefer a script-first workflow, we’ve also added support for new methods for Transitions to the StyleRule class! You can set transitions for individual properties or batch them together using a dictionary. Check out the technical documentation here.

Here’s an example of how you can create another hover transition using scripts. You can find this script in the above sample placefile as well.

Click here to view the script:
local ReplicatedStorage = game:GetService("ReplicatedStorage")

if not script.Parent.Enabled then return end

-- 1. Create the StyleSheet
local sheet = Instance.new("StyleSheet")
sheet.Name = "ScriptedDemo"
sheet.Parent = script 

-- 2. Create the Base Rule for the Frame
local baseRule = Instance.new("StyleRule")
baseRule.Selector = ".Tagged"
baseRule.Name = ".Tagged"
baseRule:SetProperties({
	BackgroundColor3 = Color3.fromRGB(240, 240, 240),
	Size = UDim2.fromOffset(100, 100),
})
baseRule:SetPropertyTransitions({
	["*"] = TweenInfo.new(0.25),

	BackgroundColor3 = TweenInfo.new(
		0.5, 						-- Duration
		Enum.EasingStyle.Cubic, 	-- EasingStyle
		Enum.EasingDirection.Out, 	-- EasingDirection
		0, 							-- RepeatCount
		false,						-- Reverses
		0 						    -- Delay
	),
})
baseRule.Parent = sheet


-- 3. Create the Base Pseudo-Instance Rule for UICorner
local baseCornerRule = Instance.new("StyleRule")
baseCornerRule.Selector = ".Tagged::UICorner"
baseCornerRule.Name = ".Tagged::UICorner"
baseCornerRule:SetProperty("CornerRadius", UDim.new(0, 0))
-- Make sure the corner radius also smoothly transitions!
baseCornerRule:SetPropertyTransitions({
	["*"] = TweenInfo.new(0.25)
})
baseCornerRule.Parent = sheet

-- 4. Create the Hover Rule for the Frame
local hoverRule = Instance.new("StyleRule")
hoverRule.Selector = ".Tagged:Hover" -- Using standard capitalized :Hover for Roblox GuiStates
hoverRule.Name = ".Tagged:Hover"
hoverRule:SetProperties({
	BackgroundColor3 = Color3.fromRGB(50, 95, 255),
	Size = UDim2.fromOffset(125, 125),
})
hoverRule.Parent = sheet

-- 5. Create the Hover Pseudo-Instance Rule for UICorner
local hoverCornerRule = Instance.new("StyleRule")
hoverCornerRule.Selector = ".Tagged:Hover::UICorner"
hoverCornerRule.Name = ".Tagged:Hover::UICorner"
hoverCornerRule:SetProperty("CornerRadius", UDim.new(1, 0))
hoverCornerRule.Parent = sheet

-- 6. Create the StyleLink
local styleLink = Instance.new("StyleLink")
styleLink.Name = "ScriptedDemoLink"
styleLink.StyleSheet = sheet
styleLink.Parent = script.Parent

-- 7. Create the Frame and apply the tag
local frame = Instance.new("Frame")
frame.Parent = script.Parent
frame.Position = UDim2.new(0.5, 0, 0.1, 0)
frame.AnchorPoint = Vector2.new(0.5, 0.5)
frame:AddTag("Tagged")

At run-time, the script above generates the below UI and applies the transition!

Release Notes

  • Trigger Constraints: Transitions only fire when a property is changed via the Styling system (like a Tag or GuiState change). They will not fire for non-styling changes, like size or position changes due to layout.

  • Priority Hierarchy: Remember that a StyleRule’s priority affects the order in which rules are applied. To ensure a transition isn’t ignored, its StyleRule must have a higher Priority value (or be positioned above the base rule in the Style Editor) so it correctly overrides the default style.

  • Performance: Transitions are handled natively by the engine, offering better performance than manual Luau tweening, and performance won’t be a problem unless you have hundreds of Transitions playing concurrently. Note that per-property transitions are more performant than default transitions.

  • TweenService: We are not deprecating TweenService; Transitions integrate tween capabilities directly into the Styling ecosystem.

:blue_heart: Made with love

New Styling features were made possible thanks to @TangyTrout, @uiuxartist, @DrRanchDressing, and @IgnisRBX. While you’re testing out Transitions, we’ll be hard at work building the next set of UI features to ensure you have the best systems for your UI projects.

We can’t wait to hear your thoughts and see all the amazing things you create! Let us know about your experience and if you encounter any issues! :grinning_face_with_smiling_eyes:

207 Likes

This topic was automatically opened after 10 minutes.

This is revolutionary! I’ve always had trouble organizing my UI animations, Thank you Roblox!
(also pleaaase lower the highly engaged players required)

43 Likes

This is cool! Keep doing these weekly ui updates please :folded_hands:t3:

10 Likes

I am really looking forward to all these UI updates since there are still so many possibilities to be added. I am hoping that the various UI bugs that have existed for years and are yet to be looked into will get fixed soon!

3 Likes

The UI team is lowkey cooking…
can’t say that for the others

22 Likes

Literally was praying this would come sooner so i could potentially removed the need for my animation effect module

1 Like

Glad to see this is finally in beta, how long do you expect it to be in studio beta I’d love to be able to use it in game

1 Like

Really good update. Props to the ui team.

2 Likes

Woah, well that’s really cool. :fire: feature

3 Likes

Great update! I’m curious if there are any plans to support attributes as selectors. For example, it would be useful to have mutually exclusive styles. For example, take a .Button tag selector, it could have attribute subselectors ButtonStyle=Primary and ButtonStyle=Secondary. This is cleaner, in my opinion, than having a long list of tags applied to a instance.

3 Likes

Is there a way to make this work? rather than inputting a size property on the transition. That way it works with any UI.

Edit: I played around a bit more and manage to make it work. I forgot UIScale probably gets added only on hover that way it instantly scales. Awesome!

1 Like

UI designers have never ate this good before :fire::fire:

7 Likes

Please add some sort of “keyframe” rules that encode when properties should change relative to the total duration of the property transition responsible for that animation from 0% to 100%. This would let people create more complex sequences in a way that isn’t possible without orchestrating things programmatically anyways. Other than that, great work!

3 Likes

Is there going to be support for springs using TweenService:SmoothDamp()?
As its a bit odd considering how popular they are with UI that they aren’t included.

3 Likes

Never thought I’d see the day where this feature would actually be released. I GENUINELY used to pray for times like these.

8 Likes

WE EATING GOOD THIS WEEKEND.

(i can finally get rid of the performance blackhole that is my animation module)

2 Likes

My one and only complaint left is the Interface design.

It feels really barebones and doesn’t fit with the studio design

1 Like

Are declarative UI libraries getting cooked? :thinking:

2 Likes

rll cool but i gotta ask for anti allysing sorry for the grammar lol but yea with all this new awesome UI updates that will be so huge to be able to rotate frames withouth having rll pixelated lines keep it up though :flexed_biceps:

1 Like