HTML Code Works Different In Streamlit (General Problem)

Summary

While there is a video effect in the HTML and CSS files, this effect does not work when the same code is run in the streamlit.

I’ve had this problem before. Is this a general problem or is there a feature I’m not aware of?

Steps to reproduce

The video file must also be in the folder.

smoke video link: smoke.mp4 - Google Drive

Code snippet:

import streamlit as st

# Page config
st.set_page_config(
        page_title= "Multipage App",
        page_icon="📁")


# Customization for sidebar
st.markdown('<style>div[class="css-6qob1r e1fqkh3o3"] { background: url("https://media2.giphy.com/media/46hpy8xB3MiHfruixn/giphy.gif");background-repeat: no-repeat;background-size:350%;border:1px solid #36454F; border-top:none;} </style>', unsafe_allow_html=True)

# Hiding the Footer
hide_st_style =" <style>footer {visibility: hidden;}</style>"
st.markdown(hide_st_style, unsafe_allow_html=True)  


st.markdown("""
  <style>
      ul[class="css-uc76bn e1fqkh3o9"]{
        position: relative;
        position: relative;
        padding-top: 3rem;
        display: flex;
        justify-content: center;
        flex-direction: column;
        align-items: left;
      }
      
      
      .css-17lntkn {
        font-weight: bold;
        font-size: 24px;
        color: yellow;
        font-family: arial;
        border:black;
      }
      
      .css-pkbazv {
        font-weight: bold;
        font-size: 24px;
        color: yellow;
        font-family: arial;
      }
  </style>""", unsafe_allow_html=True)


st.markdown("""
<body>
<section>
<video src="smoke.mp4" autoplay muted></video>




<h1>
<span>W</span>
<span>E</span>
<span>L</span>
<span>C</span>
<span>O</span>
<span>M</span>
<span>E</span>
</h1> 
</section>


<style>


body 
  {
  margin: 0;
  padding: 0;
  background:black;
  }

section
  {
  height:100vh;
  background:#000; 
  

  }

video
  {
  object-fit:cover;
  }
   
h1
 {
 margin:0;
 padding:0;
 position:absolute;
 top:50%;
 transform: translateY(-50%);
 width:100%;
 text-align:center;
 color:#ddd;
 font-size:5em;
 font-family:sans-serif;
 letter-spacing:0.2em;

 }

h1 span
 {
 display:inline-block;
 animation: animate 1s linear forwards;

 }

@keyframes animate
 {
 
 0%
 { 
  opacity:0;
  transform: rotateY(90deg);
  filter:blur(10px);
 }

100%
 { 
  opacity:1;
   transform: rotateY(0deg);
   filter:blur(0px);
 }

 }


h1 span:nth-child(1)
{
 
 animation-delay: 1s;

}
	

h1 span:nth-child(2)
{
 
 animation-delay: 1.5s;

}

h1 span:nth-child(3)
{
 
 animation-delay: 2s;

}

h1 span:nth-child(4)
{
 
 animation-delay: 2.5s;

}

h1 span:nth-child(5)
{
 
 animation-delay: 3s;

}

h1 span:nth-child(6)
{
 
 animation-delay: 3.75s;

}

h1 span:nth-child(7)
{
 
 animation-delay: 4s;

}


	
</style>
	 

</body>


  


<script>
document
  .querySelector('video')
  .addEventListener('ended', function(e) {
    e.target.style.display = 'none';
  });
// ofcourse you could toggle a class that hides it
// instead of setting an inline style
</script>
</html>""",unsafe_allow_html=True)

Expected behavior:

It is expected to behave the same as HTML and CSS

Debug info

  • Streamlit version: v15.2.0
  • Python version: v3.8
  • OS version: Windows 10
  • Browser version: Chrome 108.0.5359.99

If you want to include <script> ... </script> you need to use html from components and not markdown. Markdown will render plain html and utilize <style> tags fine, but won’t run scripts.

from streamlit.components.v1 import html

html('<script> ... </script>)

Smoke effect is not working.

st.markdown("""
  <style>
      ul[class="css-uc76bn e1fqkh3o9"]{
        position: relative;
        position: relative;
        padding-top: 3rem;
        display: flex;
        justify-content: center;
        flex-direction: column;
        align-items: left;
      }
      
      
      .css-17lntkn {
        font-weight: bold;
        font-size: 24px;
        color: yellow;
        font-family: arial;
        border:black;
      }
      
      .css-pkbazv {
        font-weight: bold;
        font-size: 24px;
        color: yellow;
        font-family: arial;
      }
  </style>""", unsafe_allow_html=True)


st.markdown("""
<body>
<section>
<video src="smoke.mp4" autoplay muted></video>




<h1>
<span>W</span>
<span>E</span>
<span>L</span>
<span>C</span>
<span>O</span>
<span>M</span>
<span>E</span>
</h1> 
</section>


<style>


body 
  {
  margin: 0;
  padding: 0;
  background:black;
  }

section
  {
  height:100vh;
  background:#000; 
  

  }

video
  {
  object-fit:cover;
  }
   
h1
 {
 margin:0;
 padding:0;
 position:absolute;
 top:50%;
 transform: translateY(-50%);
 width:100%;
 text-align:center;
 color:#ddd;
 font-size:5em;
 font-family:sans-serif;
 letter-spacing:0.2em;

 }

h1 span
 {
 display:inline-block;
 animation: animate 1s linear forwards;

 }

@keyframes animate
 {
 
 0%
 { 
  opacity:0;
  transform: rotateY(90deg);
  filter:blur(10px);
 }

100%
 { 
  opacity:1;
   transform: rotateY(0deg);
   filter:blur(0px);
 }

 }


h1 span:nth-child(1)
{
 
 animation-delay: 1s;

}
	

h1 span:nth-child(2)
{
 
 animation-delay: 1.5s;

}

h1 span:nth-child(3)
{
 
 animation-delay: 2s;

}

h1 span:nth-child(4)
{
 
 animation-delay: 2.5s;

}

h1 span:nth-child(5)
{
 
 animation-delay: 3s;

}

h1 span:nth-child(6)
{
 
 animation-delay: 3.75s;

}

h1 span:nth-child(7)
{
 
 animation-delay: 4s;

}


	
</style>
	 

</body>


 
</html>""",unsafe_allow_html=True)


components.html( """<script>
document
  .querySelector('video')
  .addEventListener('ended', function(e) {
    e.target.style.display = 'none';
  });

</script>""")

Each html element is its own iframe. Can you put everything in the html element together?

(Or specify the parent document in the script)