Skip to content

Change the border size of a box in TradingView Pine Script

TL;DR
Adjust box outlines with box.set_border_width() to direct attention to the freshest price zones.

DifficultyBeginner
Time to implement5-10 min
CategoryVisual Effects
//@version=6
indicator("Box border quick start", overlay=true)
var box hiZone = na
if ta.crossover(close, ta.sma(close, 20))
hiZone := box.new(
left = bar_index,
top = high * 1.005,
right = bar_index + 6,
bottom = low * 0.995,
bgcolor = color.new(color.orange, 85)
)
if not na(hiZone)
box.set_border_width(hiZone, close > ta.sma(close, 20) ? 4 : 1)
Tip. Pair box.set_border_width() with the same identifier returned from box.new(). Updating in place means the chart never flashes or repaints the region.

Pine Script boxes are ideal for highlighting support, resistance, or signal zones, but static outlines fail to show which region is fresh. Dynamic borders let you emphasise active setups, soften older ones, and recycle drawings without recreating them. The result is a cleaner chart that still tells a story about recency and importance.

  • Persist a box identifier across bars for later edits
  • Change border widths as conditions evolve
  • Sync outlines with colour and transparency cues
  • Retire or hide outdated highlights cleanly
CallPurpose
box.new()Creates a drawing and returns the identifier you must keep to modify it later.
box.set_border_width()Changes outline thickness without recreating the box.
box.set_border_color()Updates the outline colour to match the current emphasis.
box.set_bgcolor()Adjusts fill transparency alongside border tweaks.
box.delete()Removes the drawing when the setup is invalidated.
  1. Create a box handle that persists
    Store the identifier from box.new() in a var so it survives new bars. Without it, nothing can be updated later.

    var box sessionBox = na
    if ta.change(time("D"))
    sessionBox := box.new(
    left = bar_index,
    top = high,
    right = bar_index + 1,
    bottom = low,
    bgcolor = color.new(color.blue, 90)
    )
  2. Emphasise the active zone
    Drive the outline width from your signal logic. A wide border highlights the current opportunity, while a narrow one keeps context.

    if not na(sessionBox)
    bool isHot = close > ta.sma(close, 50)
    box.set_border_width(sessionBox, isHot ? 4 : 1)
    box.set_border_color(sessionBox, isHot ? color.new(color.blue, 0) : color.new(color.gray, 40))
  3. Fade or clear stale regions
    Hide the outline when the setup invalidates, or delete the box entirely when the structure no longer matters.

    if not na(sessionBox) and ta.crossunder(close, ta.sma(close, 50))
    box.set_border_width(sessionBox, 0) // keep the fill but hide the outline
    if not na(sessionBox) and barstate.islastconfirmedhistory
    box.delete(sessionBox) // optional clean-up to prevent piling boxes
//@version=5
indicator("Dynamic zone outline", overlay=true)
length = input.int(34, "MA length")
lookaheadBars = input.int(12, "Box width (bars)")
ma = ta.sma(close, length)
trigger = ta.crossover(close, ma) or ta.crossunder(close, ma)
var box signalBox = na
if trigger
color accent = ta.crossover(close, ma) ? color.green : color.red
signalBox := box.new(
left = bar_index,
top = high * 1.003,
right = bar_index + lookaheadBars,
bottom = low * 0.997,
bgcolor = color.new(accent, 88),
border_color = accent,
border_width = 4
)
if not na(signalBox)
age = bar_index - box.get_left(signalBox)
fadingWidth = math.max(1, 4 - math.floor(age / 3))
box.set_border_width(signalBox, fadingWidth)
box.set_border_color(signalBox, color.new(box.get_border_color(signalBox), age > lookaheadBars ? 60 : 0))
plot(ma, "Signal MA", color=color.gray)
Why this works.
  • New signals get a crisp four-pixel outline and bright colour.
  • Each bar reduces the width, so attention naturally shifts to newer setups.
  • Once the age threshold is hit, colour transparency increases to avoid clutter.
  • Persist box identifiers with var or collections; local variables reset every bar.
  • box.set_border_width() expects integers—wrap dynamic calculations with math.round() if needed.
  • A width of 0 hides the outline but keeps the fill. Delete the box if you need it gone.
  • Pair width changes with colour or transparency updates so emphasis feels deliberate.

Why does my box vanish after setting the width to zero?

Section titled “Why does my box vanish after setting the width to zero?”

Setting width to 0 hides the outline. If you also set the fill to a fully transparent colour, nothing is visible. Either keep a subtle fill or recreate the box when the setup returns.

Can I style each edge of the box differently?

Section titled “Can I style each edge of the box differently?”

No. Pine Script boxes apply border settings to all four sides simultaneously. To emulate per-edge styling, overlay multiple boxes with different coordinates and widths.

  • Store the box.new() identifier so you can adjust it across future bars.
  • Use box.set_border_width() to highlight or de-emphasise zones without redrawing.
  • Combine width, colour, and transparency changes for expressive visual cues.
  • Clean up stale boxes with width 0 or box.delete() to keep charts readable.

Adapted from tradingcode.net, optimised for Algo Trade Analytics users.