# How to tweak tick label position in Makie?

**URL:** <https://discourse.julialang.org/t/how-to-tweak-tick-label-position-in-makie/60085>\
**Category:** Visualization\
**Tags:** question, plotting, makie\
**Created:** [April 27, 2021, 7:35am UTC](https://discourse.julialang.org/t/how-to-tweak-tick-label-position-in-makie/60085 "2021-04-27T07:35:10Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![ederag](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ederag/32/4106_2.png) [@ederag](https://discourse.julialang.org/u/ederag)\
**Post date:** [April 27, 2021, 7:35am UTC](https://discourse.julialang.org/t/how-to-tweak-tick-label-position-in-makie/60085/1 "2021-04-27T07:35:11Z")

</div>

The new layout system is awesome,  
and the [basic](http://makie.juliaplots.org/stable/basic-tutorial.html) and [layout](http://makie.juliaplots.org/stable/makielayout/tutorial.html) tutorials gave very good explanations.  
After reading all the docs, in particular the [Modifying ticks](http://makie.juliaplots.org/stable/makielayout/axis.html#Modifying-ticks) section,  
I see how to set the ticks strings (otherwise the last one was missing).

But ticklabels of adjacent subplots overlap.  
Here is a mwe adapted from [the documentation](http://makie.juliaplots.org/stable/makielayout/axis.html#Changing-x-and-y-axis-position):

```julia
using CairoMakie
fig = Figure(resolution = (800, 800))

for i in 1:2, j in 1:2
    Axis(fig[i, j],
        limits = (0.5, 0.7, -2, 2),
        # otherwise the 0.7 tick label is missing
        xticks = ([0.5, 0.55, 0.6, 0.65, 0.7], 
                  ["0.5", "0.55", "0.6", "0.65", "0.7"]),
        xaxisposition = (i == 1 ? :top : :bottom),
        yaxisposition = (j == 1 ? :left : :right)
    )
end
colgap!(fig.layout, 25)
rowgap!(fig.layout, 25)

```

 ![image](https://global.discourse-cdn.com/julialang/original/3X/2/4/242825baea0866001c907a6b2fefe901b348aa89.png)

Is it possible to tweak the first and last ticklabel a little bit inward ?

---

<div class="post-metadata">

**Author:** ![jules](https://avatars.discourse-cdn.com/v4/letter/j/41988e/32.png) [@jules](https://discourse.julialang.org/u/jules)\
**Post date:** [April 27, 2021, 4:50pm UTC](https://discourse.julialang.org/t/how-to-tweak-tick-label-position-in-makie/60085/2 "2021-04-27T16:50:05Z")

</div>

Yes you can, although that will only work well if you don’t change the ticks anymore after. You can set xticklabelalign for example to an array where the first tick is left aligned, the central ones center aligned, and the right tick right aligned. This just has to fit the number of ticks, which is why they shouldn’t change after.

---

<div class="post-metadata">

**Author:** ![ederag](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ederag/32/4106_2.png) [@ederag](https://discourse.julialang.org/u/ederag)\
**Post date:** [April 27, 2021, 10:50pm UTC](https://discourse.julialang.org/t/how-to-tweak-tick-label-position-in-makie/60085/3 "2021-04-27T22:50:40Z")

</div>

Thanks for the answer, I was dreaming about such a fine control !

A little trap: with  
`xticklabelalign = [:left, :center, :center, :center, :right]`  
it failed:

> **Error message**
>
> ```julia
> MethodError: no method matching getindex(::Symbol, ::Int64)
> 
> layout_text(::String, ::Float32, ::FreeTypeAbstraction.FTFont, ::Symbol, ::AbstractPlotting.Quaternionf0, ::Base.RefValue{StaticArrays.SMatrix{4, 4, Float32, 16}}, ::AbstractPlotting.Automatic, ::Float64)@layouting.jl:70
> (::AbstractPlotting.var"#164#166")(::String, ::Float32, ::FreeTypeAbstraction.FTFont, ::Symbol, ::AbstractPlotting.Quaternionf0, ::Base.RefValue{StaticArrays.SMatrix{4, 4, Float32, 16}}, ::AbstractPlotting.Automatic, ::Float64)@interfaces.jl:295
> broadcast_foreach(::Function, ::Vector{String}, ::Vararg{Any, N} where N)@utilities.jl:162
> (::AbstractPlotting.var"#163#165"{AbstractPlotting.Text{Tuple{Vector{String}}}})(::Vector{String}, ::Vector{Any}, ::Float32, ::String, ::Vector{Symbol}, ::Float32, ::StaticArrays.SMatrix{4, 4, Float32, 16}, ::AbstractPlotting.Automatic, ::Float64)@interfaces.jl:294
> (::Observables.OnUpdate{AbstractPlotting.var"#163#165"{AbstractPlotting.Text{Tuple{Vector{String}}}}, Tuple{Observables.Observable{Vector{String}}, Observables.Observable{Any}, Observables.Observable{Any}, Observables.Observable{Any}, Observables.Observable{Any}, Observables.Observable{Any}, Observables.Observable{Any}, Observables.Observable{Any}, Observables.Observable{Any}}})(::Vector{Any})@Observables.jl:334
> #invokelatest#2@essentials.jl:708[inlined]
> invokelatest@essentials.jl:706[inlined]
> notify@Observables.jl:88[inlined]
> setindex!@Observables.jl:248[inlined]
> (::Observables.var"#3#4"{Any, Observables.Observable{Any}})(::Vector{Any})@Observables.jl:58
> #invokelatest#2@essentials.jl:708[inlined]
> invokelatest@essentials.jl:706[inlined]
> notify@Observables.jl:88[inlined]
> setindex!(::Observables.Observable{Vector{Any}}, ::Vector{GeometryBasics.Point{3, Float32}})@Observables.jl:248
> (::AbstractPlotting.var"#167#168"{AbstractPlotting.Text{Tuple{Vector{String}}}, Observables.Observable{Vector{Any}}})(::Vector{Tuple{String, GeometryBasics.Point{2, Float32}}})@interfaces.jl:327
> #invokelatest#2@essentials.jl:708[inlined]
> invokelatest@essentials.jl:706[inlined]
> notify@Observables.jl:88[inlined]
> setindex!@Observables.jl:248[inlined]
> MapUpdater@Observables.jl:372[inlined]
> (::Observables.OnUpdate{Observables.MapUpdater{AbstractPlotting.var"#188#190"{Int64}, Vector{Tuple{String, GeometryBasics.Point{2, Float32}}}}, Tuple{Observables.Observable{Tuple{Vector{Tuple{String, GeometryBasics.Point{2, Float32}}}}}}})(::Tuple{Vector{Tuple{String, GeometryBasics.Point{2, Float32}}}})@Observables.jl:334
> #invokelatest#2@essentials.jl:708[inlined]
> invokelatest@essentials.jl:706[inlined]
> notify@Observables.jl:88[inlined]
> setindex!(::Observables.Observable{Tuple{Vector{Tuple{String, GeometryBasics.Point{2, Float32}}}}}, ::Tuple{Vector{Tuple{String, GeometryBasics.Point{2, Float32}}}})@Observables.jl:248
> (::Observables.MapUpdater{AbstractPlotting.var"#191#192"{UnionAll}, Tuple{Vector{Tuple{String, GeometryBasics.Point{2, Float32}}}}})(::Vector{Tuple{String, GeometryBasics.Point{2, Float32}}})@Observables.jl:372
> (::Observables.OnUpdate{Observables.MapUpdater{AbstractPlotting.var"#191#192"{UnionAll}, Tuple{Vector{Tuple{String, GeometryBasics.Point{2, Float32}}}}}, Tuple{Observables.Observable{Vector{Tuple{String, GeometryBasics.Point{2, Float32}}}}}})(::Vector{Tuple{String, GeometryBasics.Point{2, Float32}}})@Observables.jl:334
> #invokelatest#2@essentials.jl:708[inlined]
> invokelatest@essentials.jl:706[inlined]
> notify@Observables.jl:88[inlined]
> setindex!@Observables.jl:248[inlined]
> MapUpdater@Observables.jl:372[inlined]
> (::Observables.OnUpdate{Observables.MapUpdater{AbstractPlotting.var"#188#190"{Int64}, Vector{Tuple{String, GeometryBasics.Point{2, Float32}}}}, Tuple{Observables.Observable{Tuple{Vector{Tuple{String, GeometryBasics.Point{2, Float32}}}}}}})(::Tuple{Vector{Tuple{String, GeometryBasics.Point{2, Float32}}}})@Observables.jl:334
> #invokelatest#2@essentials.jl:708[inlined]
> invokelatest@essentials.jl:706[inlined]
> notify@Observables.jl:88[inlined]
> setindex!(::Observables.Observable{Tuple{Vector{Tuple{String, GeometryBasics.Point{2, Float32}}}}}, ::Tuple{Vector{Tuple{String, GeometryBasics.Point{2, Float32}}}})@Observables.jl:248
> (::AbstractPlotting.var"#203#205"{AbstractPlotting.Attributes, Observables.Observable{Tuple{Vector{Tuple{String, GeometryBasics.Point{2, Float32}}}}}, DataType})(::Tuple{}, ::Tuple{Vector{Tuple{String, GeometryBasics.Point{2, Float32}}}})@interfaces.jl:681
> (::Observables.OnUpdate{AbstractPlotting.var"#203#205"{AbstractPlotting.Attributes, Observables.Observable{Tuple{Vector{Tuple{String, GeometryBasics.Point{2, Float32}}}}}, DataType}, Tuple{Observables.Observable{Tuple{}}, Observables.Observable{Tuple{Vector{Tuple{String, GeometryBasics.Point{2, Float32}}}}}}})(::Tuple{Vector{Tuple{String, GeometryBasics.Point{2, Float32}}}})@Observables.jl:334
> #invokelatest#2@essentials.jl:708[inlined]
> invokelatest@essentials.jl:706[inlined]
> notify@Observables.jl:88[inlined]
> setindex!@Observables.jl:248[inlined]
> MapUpdater@Observables.jl:372[inlined]
> (::Observables.OnUpdate{Observables.MapUpdater{typeof(tuple), Tuple{Vector{Tuple{String, GeometryBasics.Point{2, Float32}}}}}, Tuple{Observables.Observable{Vector{Tuple{String, GeometryBasics.Point{2, Float32}}}}}})(::Vector{Tuple{String, GeometryBasics.Point{2, Float32}}})@Observables.jl:334
> #invokelatest#2@essentials.jl:708[inlined]
> invokelatest@essentials.jl:706[inlined]
> notify@Observables.jl:88[inlined]
> setindex!@Observables.jl:248[inlined]
> (::AbstractPlotting.MakieLayout.var"#153#184"{Observables.Observable{Vector{GeometryBasics.Point{2, Float32}}}, Observables.Observable{Vector{Float32}}, Observables.Observable{Float32}, Observables.Observable{Vector{Tuple{String, GeometryBasics.Point{2, Float32}}}}, Observables.Observable{Tuple{Float32, Tuple{Float32, Float32}, Bool}}, Observables.Observable{Any}, Observables.Observable{Any}})(::Vector{String}, ::Float32, ::Bool)@lineaxis.jl:311
> (::Observables.OnUpdate{AbstractPlotting.MakieLayout.var"#153#184"{Observables.Observable{Vector{GeometryBasics.Point{2, Float32}}}, Observables.Observable{Vector{Float32}}, Observables.Observable{Float32}, Observables.Observable{Vector{Tuple{String, GeometryBasics.Point{2, Float32}}}}, Observables.Observable{Tuple{Float32, Tuple{Float32, Float32}, Bool}}, Observables.Observable{Any}, Observables.Observable{Any}}, Tuple{Observables.Observable{Vector{String}}, Observables.Observable{Float32}, Observables.Observable{Any}}})(::Vector{String})@Observables.jl:334
> #invokelatest#2@essentials.jl:708[inlined]
> invokelatest@essentials.jl:706[inlined]
> notify@Observables.jl:88[inlined]
> setindex!@Observables.jl:248[inlined]
> (::AbstractPlotting.MakieLayout.var"#140#171"{Observables.Observable{Vector{String}}, Observables.Observable{Vector{GeometryBasics.Point{2, Float32}}}, Observables.Observable{Vector{Float32}}, Observables.Observable{Tuple{Float32, Tuple{Float32, Float32}, Bool}}, Observables.Observable{Any}, AbstractPlotting.Attributes})(::Tuple{Vector{Float64}, Vector{String}}, ::Bool)@lineaxis.jl:242
> (::Observables.OnUpdate{AbstractPlotting.MakieLayout.var"#140#171"{Observables.Observable{Vector{String}}, Observables.Observable{Vector{GeometryBasics.Point{2, Float32}}}, Observables.Observable{Vector{Float32}}, Observables.Observable{Tuple{Float32, Tuple{Float32, Float32}, Bool}}, Observables.Observable{Any}, AbstractPlotting.Attributes}, Tuple{Observables.Observable{Tuple{Vector{Float64}, Vector{String}}}, Observables.Observable{Any}}})(::Tuple{Vector{Float64}, Vector{String}})@Observables.jl:334
> #invokelatest#2@essentials.jl:708[inlined]
> invokelatest@essentials.jl:706[inlined]
> notify@Observables.jl:88[inlined]
> setindex!(::Observables.Observable{Tuple{Vector{Float64}, Vector{String}}}, ::Tuple{Vector{Float64}, Vector{String}})@Observables.jl:248
> (::Observables.MapUpdater{AbstractPlotting.MakieLayout.var"#139#170", Tuple{Vector{Float64}, Vector{String}}})(::Tuple{Float32, Tuple{Float32, Float32}, Bool}, ::Vararg{Any, N} where N)@Observables.jl:372
> (::Observables.OnUpdate{Observables.MapUpdater{AbstractPlotting.MakieLayout.var"#139#170", Tuple{Vector{Float64}, Vector{String}}}, Tuple{Observables.Observable{Tuple{Float32, Tuple{Float32, Float32}, Bool}}, Observables.Observable{Any}, Observables.Observable{Any}, Observables.Observable{Any}, Observables.Observable{Any}}})(::Tuple{Float32, Float32})@Observables.jl:334
> #invokelatest#2@essentials.jl:708[inlined]
> invokelatest@essentials.jl:706[inlined]
> notify@Observables.jl:88[inlined]
> setindex!(::Observables.Observable{Any}, ::Tuple{Float32, Float32})@Observables.jl:248
> var"#LineAxis#129"(::Base.Iterators.Pairs{Symbol, Observables.Observable, NTuple{36, Symbol}, NamedTuple{(:endpoints, :limits, :flipped, :ticklabelrotation, :ticklabelalign, :labelsize, :labelpadding, :ticklabelpad, :labelvisible, :label, :labelfont, :ticklabelfont, :ticklabelcolor, :labelcolor, :tickalign, :ticklabelspace, :ticks, :tickformat, :ticklabelsvisible, :ticksvisible, :spinevisible, :spinecolor, :spinewidth, :ticklabelsize, :trimspine, :ticksize, :reversed, :tickwidth, :tickcolor, :minorticksvisible, :minortickalign, :minorticksize, :minortickwidth, :minortickcolor, :minorticks, :scale), Tuple{Observables.Observable{Tuple{GeometryBasics.Point{2, Float32}, GeometryBasics.Point{2, Float32}}}, Observables.Observable{Tuple{Float32, Float32}}, Observables.Observable{Bool}, Observables.Observable{Any}, Observables.Observable{Any}, Observables.Observable{Any}, Observables.Observable{Any}, Observables.Observable{Any}, Observables.Observable{Any}, Observables.Observable{Any}, Observables.Observable{Any}, Observables.Observable{Any}, Observables.Observable{Any}, Observables.Observable{Any}, Observables.Observable{Any}, Observables.Observable{Any}, Observables.Observable{Any}, Observables.Observable{Any}, Observables.Observable{Any}, Observables.Observable{Any}, Observables.Observable{Bool}, Observables.Observable{Symbol}, Observables.Observable{Any}, Observables.Observable{Any}, Observables.Observable{Any}, Observables.Observable{Any}, Observables.Observable{Any}, Observables.Observable{Any}, Observables.Observable{Any}, Observables.Observable{Any}, Observables.Observable{Any}, Observables.Observable{Any}, Observables.Observable{Any}, Observables.Observable{Any}, Observables.Observable{Any}, Observables.Observable{Any}}}}, ::Type{AbstractPlotting.MakieLayout.LineAxis}, ::AbstractPlotting.Scene)@lineaxis.jl:382
> var"#layoutable#199"(::Nothing, ::Base.Iterators.Pairs{Symbol, Any, NTuple{5, Symbol}, NamedTuple{(:limits, :xticks, :xticklabelalign, :xaxisposition, :yaxisposition), Tuple{Tuple{Float64, Float64, Int64, Int64}, Tuple{Vector{Float64}, Vector{String}}, Vector{Symbol}, Symbol, Symbol}}}, ::typeof(AbstractPlotting.MakieLayout.layoutable), ::Type{AbstractPlotting.MakieLayout.Axis}, ::AbstractPlotting.Figure)@axis.jl:196
> #_layoutable#11@layoutables.jl:63[inlined]
> #_layoutable#10@layoutables.jl:58[inlined]
> #_#9@layoutables.jl:49[inlined]
> top-level scope@Local: 7[inlined]
> 
> ```

This is understandable since the [documentation](http://makie.juliaplots.org/stable/makielayout/reference.html#AbstractPlotting.MakieLayout.Axis) says

> `xticklabelalign`  
> The horizontal and vertical alignment of the xticklabels.

But it might make sense to accept a vector of horizontal alignments for the xticklabels.

For now (CairoMakie 0.4.4, AbstractPlotting 0.17.4), one has to specify both the horizontal and vertical alignments  
(and since the label is always upright, it makes sense that the vertical alignment has to be changed for the top row)

Here is the updated example:

```julia
using CairoMakie
fig = Figure(resolution = (800, 800))

for i in 1:2, j in 1:2
    # otherwise the 0.7 tick label is missing
    xticks_values = [0.5, 0.55, 0.6, 0.65, 0.7]
    # no %g equivalent yet
    xticks_strings = ["0.5", "0.55", "0.6", "0.65", "0.7"]
    # between 0 (no shift) and 0.5 (justified)
    xticklabel_relative_shift = 0.3
    N_xticklabel = length(xticks_values)
    xticklabel_halign = fill(0.5, N_xticklabel)
    xticklabel_halign[begin] -= xticklabel_relative_shift
    xticklabel_halign[end] += xticklabel_relative_shift
    xticklabel_valign = fill(i == 1 ? :bottom : :top, N_xticklabel)
    xticklabelalign = collect(zip(xticklabel_halign, xticklabel_valign))
    Axis(fig[i, j];
        limits = (0.5, 0.7, -2, 2),
        xticks = (xticks_values, xticks_strings),
        xticklabelalign,
        xaxisposition = (i == 1 ? :top : :bottom),
        yaxisposition = (j == 1 ? :left : :right)
    )
end
colgap!(fig.layout, 25)
rowgap!(fig.layout, 25)

```

 ![image](https://global.discourse-cdn.com/julialang/original/3X/f/b/fb803528a9e514a916f18a6405c6a5d5db9e8f33.png)

---

<div class="post-metadata">

**Author:** ![bert](https://avatars.discourse-cdn.com/v4/letter/b/9e8a1a/32.png) [@bert](https://discourse.julialang.org/u/bert)\
**Post date:** [April 2, 2024, 6:31pm UTC](https://discourse.julialang.org/t/how-to-tweak-tick-label-position-in-makie/60085/4 "2024-04-02T18:31:11Z")

</div>

This is a neat solution, but I saved myself a lot of work by simply making the axes limits slightly wider with `xlims!` and `ylims!`. In this case, making them, say, 0.48 and 0.72 just to add a tiny bit of padding. The tick labels should still remain “nice”
