I am making a website in Streamlit. With HTML and CSS, I’m trying to put a clickable logo on the top left corner, and text dead center on the same line, regardless of the logo placement. I have managed to make the logo clickable when it is not located on the same line of the logo with base64 encoding. However, when I try to use div tricks to put logo and title on the same line without affecting placement of the title, only the top of the logo is clickable. Can someone explain where my code went wrong?
import base64
from typing import Final
from pathlib import Path
import streamlit as st
HOME_DIR: Final = Path(__file__).parent.resolve()
TITLE: Final = "Example page"
@st.cache_data(persist="disk")
def clickable_image(img_path: str, link: str) -> str:
"""By default, st.image doesn't support adding hyperlinks to a local image, so I
have to decode a local image to base64 and pass it to HTML markdown instead.
Parameters:
-----------
img_path : str
Path to where your image is stored.
link : str
URL which you would like to open when the image is clicked on.
Returns:
-----------
str
A cached hyperlink where your local image is stored inside via base64 encoding.
"""
img_path = HOME_DIR / img_path
img_bytes, ext = img_path.read_bytes(), img_path.suffix
encoded_img = base64.b64encode(img_bytes).decode()
return (
f'<div style="display: inline-block;">'
f'<a href="{link}" target="_blank">'
f'<img src="data:image/{ext};base64,{encoded_img}" width="100"></a>'
f"</div>"
)
def pretty_title(title: str, img_path: str, link: str) -> None:
"""Make a centered title, and give it a red line. Adapted from
'streamlit_extras.colored_headers' package.
Parameters:
-----------
title : str
The title of your page.
img_path : str
Path to where your image is stored.
link : str
URL which you would like to open when the image is clicked on.
"""
# Define the logo and text
logo_html = clickable_image(img_path, link)
text_html = "<h2 style='text-align: center; margin-top: 0;'>" f"{title}</h2>"
# Define the HTML for the logo and text side by side
html = (
"<div style='position: relative;'>"
f"<div style='position: absolute; top: 0; left: 0;'>{logo_html}</div>"
f"<div style='text-align: center;'>{text_html}</div>"
"</div>"
"<hr style='background-color: #ff4b4b; margin-top: 0;"
" margin-bottom: 0; height: 3px; border: none; border-radius: 3px;'></hr>"
)
# Render the HTML in the Streamlit app
st.markdown(html, unsafe_allow_html=True)
def main() -> None:
st.set_page_config(
page_title=TITLE,
page_icon="📖",
layout="wide"
)
pretty_title(TITLE, "logo.png", "https://www.google.com/")
main()
I solved this by setting a higher z-index
priority to the image div:
"<div style='position: relative; z-index: 1'>"
f"<div style='position: absolute; top: 0; left: 0; z-index: 2'>{logo_html}</div>"