To create 3 columns, pick the center one and add a button to it, you can use:
import streamlit as st # 1.18.1
if st.columns(3)[1].button("click me"):
st.write("clicked")
This doesn't center the button within the column, though, so hacking the CSS seems to be a current option, but I suspect the classes aren't reliable:
style = "<style>.row-widget.stButton {text-align: center;}</style>"
st.markdown(style, unsafe_allow_html=True)
with st.empty():
if st.button("click me"):
st.button("clicked!")
Another centering approach, following existing answers, is to force the button's container to be smaller so it takes up most or all of the space in it, functionally centering it:
col = st.columns(7)[3] # use an odd number and pick the middle element
clicked = col.button("click me")
Better than that might be to keep 3 columns, but make the first and last large and fit the middle one roughly to the button size. Adjust to taste:
col = st.columns((3, 1, 3))[1] # adjust to taste, possibly using floats
clicked = col.button("click me")
Removing the flex property with custom CSS might help make this robust to different screen sizes so the button text doesn't squish when shrunk.
None of these approaches are entirely satisfactory, so I'm curious to hear any new developments.
See also How to center the title and an image in streamlit?.