SevenSegment | Create 7-segment displays with ease!

The SevenSegment Module!

Welcome to SevenSegment. A very light-weight UI module that allows you to create highly customisable and performant 7-segment displays in roblox with little to no effort!

No more do you have to fake this effect with static images, or use fonts that are close enough, as you can now have the real thing that can be treated like text with heaps of customisability!


A display can be created and have a row of 7-segment characters that can display all 10 numbers along a few letters and symbols. A display also has many properties and methods to change it’s current displaying characters, layout and appearance!


Here’s a couple of example usages:

Digital Alarm Clock Display


Get SevenSegment

SevenSegment Demo Place.rbxl (56.6 KB)

How to use?

Using the SevenSegment module to create 7-segment displays can be really simple and quick! All you need is a GUI or SurfaceGUI with a frame positioned and scaled for your display.

Basic Usage
local SevenSegment = require(Gui.SevenSegment) -- The module itself

local Display = -- Creates a default white single digit display
Display:Set(4) -- Display the number 4

Here we have just created a barebones single digit 7-segment display showing a number 4. Incredible!

Now for most people, 1 digit isn’t enough, so if we want to, we can add an optional paramter when we create our display to include more usable digits:

local SevenSegment = require(Gui.SevenSegment) -- The module itself

local Display =, 5) -- Creates a 5 digit display

--Display:Set(4) -- This method is only good for setting a single selected digit
Display:SetText(12345) -- Display a range of numbers


Now we have a nice 5 digit display showing 5 numbers

Customising Displays

With the function, there is a third optional parameter you can use which lets you customise the appearance of your display with a DisplayInfo object, which is a table of your desired settings!

Here’s a nice example:

local SevenSegment = require(Gui.SevenSegment) -- The module itself

local DisplayInfo = {
	OnColour =, 0.3, 0.3), -- Segment on colour
	OffColour =, -- Segment off colour (instead of being invisible)
	Italics = true, -- Skews the digits

-- Creates a typical italics red display like a digital alarm clock!
local Display =, 5, DisplayInfo) 



If you wanted to go further, you can also add or remove as many valid parameters in that DisplayInfo table as you desire.

Here are all the current valid parameters of a DisplayInfo table that you can use. The values you see are the internal default values:

DisplayInfo = {
	OnColour =, 1, 1), -- Lit segments colour
	OffColour = nil, -- The unlit segment colours of the. Hides the segments instead if empty
	Thickness = nil, -- In pixels. Automatically scales dynamically when empty
	SeamSize = 1.5, -- A percentage based off Thickness.
	Italics = false, -- Italics/skewed style
	HorizontalAlignment = Enum.HorizontalAlignment.Left, -- Where the digits get aligned
	LayoutSpacing =, 15) -- The padding between each digit

Here’s a really cool segment display I made that uses all parameters displaying the word HELLO:

local SevenSegment = require(Gui.SevenSegment) -- The module itself

DisplayInfo = {
	OnColour =, 1, 0.4),
	OffColour =, 0.2, 0),
	Thickness = 4,
	SeamSize = 1,
	Italics = true,
	HorizontalAlignment = Enum.HorizontalAlignment.Center,
	LayoutSpacing =, 0)

local Display =, 5, DisplayInfo)

Display:SetText("HELLO") -- Supports a few letters!

How do I get this to work?

local Gui = script.Parent
local Frame = Gui:WaitForChild("MainFrame")

local SevenSegment = require(Gui:WaitForChild("SevenSegment"))

local Display =, 2) -- Creates a 5 digit display

--Display:Set(4) -- This method is only good for setting a single selected digit
Display:SetText(99) -- Display a range of numbers

1 Like

Your script looks like it is under workspace and your using a local script instead of a server script. Local scripts cannot run under workspace.

Change the local script to be a regular script instead or move the script to a client-based container. Such as starter character scripts, or starter gui, etc

1 Like

Fixed a few issues & added slight improvements. Nothin’ major.

	================== SevenSegment ===================
	Created by: Ethanthegrand (@Ethanthegrand14)
	Last updated: 14/08/2023
	Version: 1.0.0
	Learn how to use the module here:
	====================== API ========================
	> SevenSegment Module Functions : GuiObject, Digits : number?, DisplayInfo : table?)
			- Creates and returns a new Display object with an optional amount of digits and a DisplayInfo
			  to affect appearance.
	> Display Object Methods
		Display:Set(Character : number | string, DigitIndex: number?)
			- Changes the selected digit/character in the row.
			- If DigitIndex is empty, it will default to the first 
			  digit in your display.
		Display:SetText(Text : string | number)
			- Changes the entire row of characters from a given string or number.
		Display:SetColours(OnColour : Color3, OffColour : Color3?, DigitIndex: number?)
			- Changes the selected digit segment colours.
			- If OffColour is left empty or set to nil, it will use visibility instead of a colour.
			- If DigitIndex is left empty, then all digits will be affected
		Display:SetVisibility(Visible : boolean, DigitIndex: number?)
			- Changes the selected digit segment colours.
			- If OffColour is left empty or set to nil, it will use visibility instead of a colour.
			- If DigitIndex is left empty, then all digits will be affected
			- Destroys the Display object and all related instances and frames
			  that were created.
	=============== DisplayInfo ================
	Here are all the valid parameters of a DisplayInfo table which you can feed into the function to customise your display:
	DisplayInfo = {
		OnColour : Color3,
		OffColour : Color3,
		Thickness : number,
		SeamSize : number,
		Italics : boolean,
		HorizontalAlignment : Enum.HorizontalAlignment,
		LayoutSpacing : UDim

type DisplayInfoType = {
	OnColour: Color3,
	OffColour: Color3?,
	Thickness: number?,
	SeamSize: number?,
	Italics: boolean?,
	HorizontalAlignment: Enum.HorizontalAlignment?,
	LayoutSpacing: UDim?

local MainModule = {}

local CharacterSheet = require(script:WaitForChild("CharacterSheet"))
local SegmentDisplayTemplate = script:WaitForChild("SegmentDisplayTemplate")
local SegmentDisplayItalicsTemplate = script:WaitForChild("SegmentDisplayItalicsTemplate")

function GuiObject, Digits: number?, DisplayInfo: DisplayInfoType?)
	assert(Frame and Frame:IsA("GuiObject"), "Module Error - Argument 1. Please provide a valid GuiObject")
	local RowContainer: Frame ="Frame")
	RowContainer.AutomaticSize = Enum.AutomaticSize.X
	RowContainer.BackgroundTransparency = 1
	RowContainer.Size = UDim2.fromScale(1, 1)
	RowContainer.Name = "SegmentDisplayRow"
	RowContainer.Parent = Frame
	RowContainer.Visible = true
	-- Set up main display properties
	local Thickness: number = math.ceil(RowContainer.AbsoluteSize.Y / 12)
	local ItalicsEnabled: boolean = false
	local SeamSize: number = 1.5
	local SegmentOnColour: Color3 =, 1, 1)
	local SegmentOffColour: Color3
	local HorizontalAlignment: Enum.HorizontalAlignment = Enum.HorizontalAlignment.Left
	local LayoutSpacing: UDim =, 15)
	local AutomaticScaling = not DisplayInfo or not DisplayInfo.Thickness
	if DisplayInfo then
		-- Segment colouring
		SegmentOnColour = DisplayInfo.OnColour or SegmentOnColour
		SegmentOffColour = DisplayInfo.OffColour or SegmentOffColour
		-- Segment sizing and offset
		Thickness = DisplayInfo.Thickness or Thickness
		SeamSize = DisplayInfo.SeamSize or SeamSize
		ItalicsEnabled = DisplayInfo.Italics or ItalicsEnabled
		HorizontalAlignment = DisplayInfo.HorizontalAlignment or HorizontalAlignment
		LayoutSpacing = DisplayInfo.LayoutSpacing or LayoutSpacing
	-- Create display(s)
	local SegmentDisplay = {
		Frame = Frame,
		DigitCount = Digits or 1,
		-- Properties
		OnColour = SegmentOnColour,
		OffColour = SegmentOffColour,
		-- Internal variables
		CurrentDisplays = {}

	local ListLayout ="UIListLayout")
	ListLayout.FillDirection = Enum.FillDirection.Horizontal
	ListLayout.HorizontalAlignment = HorizontalAlignment or Enum.HorizontalAlignment.Left
	ListLayout.Padding = LayoutSpacing
	ListLayout.SortOrder = Enum.SortOrder.LayoutOrder
	ListLayout.Parent = RowContainer
	local TemplateToUse
	if ItalicsEnabled then
		TemplateToUse = SegmentDisplayItalicsTemplate
		TemplateToUse = SegmentDisplayTemplate
	local function AdjustSegmentFrames(FramesTable)
		local AbsoluteThickness = Thickness
		local PixelSeamSize = (AbsoluteThickness / 2) * SeamSize
		for i, Segment in ipairs(FramesTable) do
			if i == 1 or i == 4 or i == 7 then 
				-- Horizontal segments
				Segment.Size =, -AbsoluteThickness, 0, AbsoluteThickness)
				Segment.Size =, -PixelSeamSize, 0, AbsoluteThickness)

		-- Adjust vertical segment proportions
		FramesTable[2].Position =, -AbsoluteThickness / 2, 0.25, AbsoluteThickness / 4)
		FramesTable[6].Position =, AbsoluteThickness / 2, 0.25, AbsoluteThickness / 4)

		FramesTable[3].Position =, -AbsoluteThickness / 2, 0.75, -AbsoluteThickness / 4)
		FramesTable[5].Position =, AbsoluteThickness / 2, 0.75, -AbsoluteThickness / 4)
	if AutomaticScaling then
		Thickness = math.ceil(RowContainer.AbsoluteSize.Y / 12)
	for i = 1, SegmentDisplay.DigitCount do
		local DisplayFrame = TemplateToUse:Clone()
		DisplayFrame.Name = "SegmentDisplay" .. i
		DisplayFrame.Parent = RowContainer
		DisplayFrame.LayoutOrder = i
		DisplayFrame.Visible = true

		local SegmentFrames = {
		local DisplayProperties = { -- Individual seven segment display
			EnabledSegments = {false, false, false, false, false, false, false},
			OnColour = SegmentOnColour,
			OffColour = SegmentOffColour,
			SegmentFrames = SegmentFrames,
			IsVisible = true
		for i, Segment in ipairs(SegmentFrames) do
			if SegmentOffColour then
				Segment.ImageColor3 = SegmentOffColour
				Segment.Visible = false


		table.insert(SegmentDisplay.CurrentDisplays, DisplayProperties)	
	local AutoScaleConnection: RBXScriptConnection
	-- Automatically rescale the segments
	if AutomaticScaling then
		AutoScaleConnection = RowContainer:GetPropertyChangedSignal("AbsoluteSize"):Connect(function()
			Thickness = math.ceil(RowContainer.AbsoluteSize.Y / 12)
			for i = 1, SegmentDisplay.DigitCount do
	-- Methods
	function SegmentDisplay:Set(Character: number | string, DigitIndex: number?)
		DigitIndex = DigitIndex or 1
		if DigitIndex > #self.CurrentDisplays then return end
		assert(Character and tostring(Character), "Module Error - Arugment 1. Invalid number/string")
			DigitIndex and tonumber(DigitIndex) and math.floor(DigitIndex) == DigitIndex, 
			"Module Error - Argument 2. Invalid value. DisplayPosition must be an interger"
		local Display = self.CurrentDisplays[DigitIndex]
		if not Display.IsVisible then return end

		local SegmentData = CharacterSheet[tostring(Character)] -- Number, symbol, letter

		if not SegmentData then
			SegmentData = CharacterSheet[tostring(Character):lower()] -- lowercase letter
		if not SegmentData then
			-- Invalid character
			for i, Segment in ipairs(Display.SegmentFrames) do
				if self.OffColour then
					Segment.ImageColor3 = self.OffColour
					Segment.Visible = false
		-- Set the segments
		for i, Segment in ipairs(Display.SegmentFrames) do
			local Lit = SegmentData[i] and SegmentData[i] == 1
			Display.EnabledSegments[i] = Lit

			if Lit then
				Segment.Visible = true
				Segment.ImageColor3 = self.OnColour
			elseif self.OffColour then
				Segment.ImageColor3 = self.OffColour
				Segment.Visible = false

	function SegmentDisplay:SetText(Text: string | number)
		local StringText: string = ""

		assert(Text and tostring(Text), "Module Error - Argument 1. Please provide a valid string or number")

		if typeof(Text) == "number" then
			StringText = tostring(math.floor(Text))  -- convert the floored number to a string
			StringText = tostring(Text)

		local Characters = string.split(StringText, "")

		for i = 1, #self.CurrentDisplays do
			if Characters[i] then
				self:Set(Characters[i], i)
				self:Set("", i)
	function SegmentDisplay:SetColours(OnColour: Color3, OffColour: Color3?, DigitIndex: number?)	
		assert(OnColour and typeof(OnColour) == "Color3", "Module Error - Argument 1. Please provide a valid Color3 value")
		assert(not OnColour or typeof(OnColour) == "Color3", "Module Error - Argument 2. Please provide a valid Color3 value")
		local function AdjustDisplay(Display)
			self.OnColour = OnColour
			if OffColour then
				self.OffColour = OffColour
			if Display.IsVisible then
				for i, SegmentFrame in ipairs(Display.SegmentFrames) do
					if Display.EnabledSegments[i] then
						SegmentFrame.ImageColor3 = OnColour
					elseif OffColour then
						SegmentFrame.ImageColor3 = OffColour
						SegmentFrame.Visible = true
		if DigitIndex then	
			for i, Display in ipairs(self.CurrentDisplays) do
	function SegmentDisplay:SetVisibility(Visible: boolean, DigitIndex: number?)	
		local function SetDisplay(Display)
			for i: number, Segment in ipairs(Display.SegmentFrames) do
				if Display.EnabledSegments[i] and Visible then
					Segment.ImageColor3 = self.OnColour
					Segment.Visible = true
				elseif self.OffColour and Visible then
					Segment.ImageColor3 = self.OffColour
					Segment.Visible = true
					Segment.Visible = false
					Segment.ImageColor3 = self.OnColour
			Display.IsVisible = Visible
		if DigitIndex then	-- Selected display
		else -- Whole row
			for i, Display in ipairs(self.CurrentDisplays) do
	function SegmentDisplay:Destroy()
		if AutoScaleConnection then
	return SegmentDisplay

return MainModule

oh, very nice. Thank you very much for your contribution, I have updated the module.

This was very much needed too.


I have no idea why you made this, but it is very cool and I might use it.

Awesome. I hope more people stumble across this, because as subtle as it may seem, this is very useful.

Thank you for making this!

1 Like

whats need of putting module in every single object you need to have 7sg???

and how did u make stopwatch? like i mean the : and . symbols?

I just used regular text labels as dots cannot be displayed on the regular segments

I just found out that this module won’t work in a while task.wait() do and workspace.Value.Changed scripts. Big sadge :frowning:
No matter what i do it sets the segments and when the value is changed, they do not change at all. Any idea why this happens? If not please change your module to work that way, possibly.

That’s odd. Can you show me one of your scripts you used?

It shouldn’t matter how/when you update the text, it should just work either way