javascripthtmlcssresponsive-designchat

Responsive sidebar inside a floating / full-screen chat widget – HTML, CSS, JS


I’m building a floating chat widget that can be

Minimized (small)

size: 400 × 600 px (bottom-right corner)

sidebar is collapsed (≈ 30 px) and can be toggled open to 100%

when the user closes / re-opens the widget, the sidebar must start collapsed again regardless of its previous state.

Maximized (fullscreen)

sidebar is always fully open 250 px and cannot be collapsed

when the user restores the widget back to the small floating mode, the sidebar must reset to the collapsed 30 px state.

Current problems

After entering full-screen and then restoring to the small mode, the sidebar retains whatever width it had (open or closed) instead of resetting to 30 px.

On desktop widths, the 30 ↔ 250 px toggle works, but the state is not reset when the widget is minimized / re-opened.

The same classes (expanded, fullwidth, etc.) are reused for both modes, so the CSS cascade keeps them alive when the user switches modes.

Minimal example

const chatLauncher = document.getElementById('chatLauncher');
const chatContainer = document.getElementById('chatContainer');
const sidebar = document.getElementById('sidebar');

function toggleChat() {
  chatContainer.style.display = 'none';
  chatLauncher.style.display = 'flex';
}
chatLauncher.addEventListener('click', () => {
  chatContainer.style.display = 'flex';
  chatLauncher.style.display = 'none';
});

function toggleFullscreen() {
  chatContainer.classList.toggle('fullscreen');
}

function toggleSidebar() {
  const isFullscreen = chatContainer.classList.contains('fullscreen');
  const isMobile = chatContainer.offsetWidth <= 400;

  if (!isFullscreen && isMobile) {
    sidebar.classList.toggle('fullwidth');
    sidebar.classList.remove('collapsed');
    sidebar.querySelector('.content').style.display =
      sidebar.classList.contains('fullwidth') ? 'block' : 'none';
  } else {
    sidebar.classList.toggle('collapsed');
    sidebar.querySelector('.content').style.display =
      sidebar.classList.contains('collapsed') ? 'none' : 'block';
  }
}
* {
  box-sizing: border-box;
}

body {
  margin: 0;
  font-family: 'Segoe UI', sans-serif;
  background: #f3f3f3;
}

/* ---------- launcher ---------- */
.chat-launcher {
  position: fixed;
  bottom: 20px;
  right: 20px;
  background: #000;
  color: #fff;
  border-radius: 50%;
  width: 48px;
  height: 48px;
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.3);
  cursor: pointer;
  z-index: 1000;
}

/* ---------- chat container ---------- */
.chat-container {
  display: none;
  height: 600px;
  width: 400px;
  max-width: 90vw;
  position: fixed;
  bottom: 80px;
  right: 20px;
  background: #fff;
  box-shadow: 0 0 12px rgba(0, 0, 0, 0.15);
  border-radius: 12px;
  overflow: hidden;
  z-index: 1001;
  transition: all .3s ease;
}

/* ---------- fullscreen overrides ---------- */
.chat-container.fullscreen {
  width: 100vw;
  height: 100vh;
  bottom: 0;
  right: 0;
  border-radius: 0;
  display: flex;
  flex-direction: row;
}

/* sidebar in fullscreen */
.chat-container.fullscreen .sidebar {
  width: 250px;
  border-right: 1px solid #ddd;
}

.chat-container.fullscreen .sidebar .content {
  display: block;
}

/* chat area in fullscreen */
.chat-container.fullscreen .container {
  display: flex;
  flex: 1 1 auto;
}

/* ---------- sidebar ---------- */
.sidebar {
  width: 60px;
  background: #fff;
  border-right: 1px solid #ddd;
  padding: 20px;
  transition: width .3s;
  flex-shrink: 0;
}

.sidebar .toggle-btn {
  font-size: 20px;
  cursor: pointer;
  margin-bottom: 20px;
}

.sidebar .content {
  display: none;
}

.sidebar.fullwidth {
  width: 100%;
  border-right: none;
}

.sidebar.fullwidth .content {
  display: block;
}

.sidebar.fullwidth~.container {
  display: none;
}

/* ---------- chat area ---------- */
.container {
  flex: 1;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  min-width: 0;
}

.header {
  background: #f5f5f5;
  padding: 10px 16px;
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.header h2 {
  flex: 1;
  text-align: center;
  font-size: 18px;
  margin: 0;
}

.header .icons {
  display: flex;
  gap: 10px;
  font-size: 20px;
  color: #333;
  cursor: pointer;
}

.blue-banner {
  background: linear-gradient(to right, #2979ff, #1976d2);
  color: white;
  padding: 15px;
  margin: 10px;
  border-radius: 10px;
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 14px;
}

.messages {
  flex: 1;
  padding: 20px;
  overflow-y: auto;
}

.message {
  margin-bottom: 20px;
}

.message.bot {
  background: #fff;
  border-radius: 10px;
  padding: 15px;
  box-shadow: 0 0 4px rgba(0, 0, 0, .1);
  max-width: 80%;
}

.message.user {
  text-align: right;
}

.message.user .bubble {
  display: inline-block;
  background: #1976d2;
  color: white;
  border-radius: 20px;
  padding: 10px 20px;
}

.timestamp {
  font-size: 12px;
  color: gray;
  margin-top: 5px;
}

.input-area {
  display: flex;
  align-items: center;
  padding: 10px;
  background: white;
  border-top: 1px solid #ccc;
}

.input-area input {
  flex: 1;
  padding: 10px;
  border: 1px solid #ccc;
  border-radius: 20px;
  outline: none;
}

.input-area button {
  background: #1976d2;
  color: white;
  border: none;
  border-radius: 50%;
  padding: 10px 15px;
  margin-left: 10px;
  cursor: pointer;
}

.upload-btn {
  margin-right: 10px;
  font-size: 12px;
  color: #1976d2;
  cursor: pointer;
}
<div class="chat-launcher" id="chatLauncher">💬</div>

<div class="chat-container" id="chatContainer">
  <!-- sidebar -->
  <div class="sidebar" id="sidebar">
    <div class="toggle-btn" onclick="toggleSidebar()">☰</div>
    <div class="content">
      <h2>{nameHere}</h2>
      <p>{descriptionHere}</p>
      <h3>Continue Conversations</h3>
      <button style="padding:10px;border:1px solid #1976d2;border-radius:10px;width:100%;margin-bottom:10px;background:#E3F2FD;color:#000;">Sender: Clickable →</button>
      <h3>Talk to our experts</h3>
      <button style="padding:10px;width:100%;margin-bottom:10px;background:#F3E5F5;border:1px solid #CCC;border-radius:10px;">👨‍💼 Support</button>
      <div style="padding: 10px; border-radius: 10px; background: linear-gradient(to right, #d1c4e9, #f8bbd0);">
        <p><strong>Need specialized help?</strong><br/>Our teams are ready to assist you with any questions</p>
        <button style="padding: 5px 10px; background: blue; color: white; border: none; border-radius: 5px;">Call Us</button>
      </div>
    </div>
  </div>

  <!-- chat -->
  <div class="container">
    <div class="header">
      <div class="icons" onclick="toggleChat()">✖</div>
      <h2>Support</h2>
      <div class="icons">
        <span onclick="alert('Call Clicked')">📞</span>
        <span onclick="toggleFullscreen()">⤢</span>
      </div>
    </div>
    <div class="blue-banner">
      📄
      <div>
        <strong>Enter your details</strong><br>
        <small>Click here to provide your information</small>
      </div>
    </div>
    <div class="messages">
      <div class="message bot">
        Hey 😃 How can I assist you with services today? Could you please share your username to help you better?
        <ul>
          <li>1. I have an issue with SMS</li>
          <li>2. I need help with Email</li>
          <li>3. Other service query</li>
        </ul>
        <div class="timestamp">10:26 am</div>
      </div>
      <div class="message user">
        <div class="bubble">hey</div>
        <div class="timestamp">10:26 am</div>
      </div>
      <div class="message bot">
        Hey 😃 How can I help you with today? Please share your username so I can assist you better.
        <ul>
          <li>1. I have an issue with SMS</li>
          <li>2. I need help with Email</li>
          <li>3. Other service query</li>
        </ul>
        <div class="timestamp">10:27 am</div>
      </div>
    </div>
    <div class="input-area">
      <span class="upload-btn">📎 Upload Files</span>
      <input type="text" placeholder="Message AI Assistant...">
      <button>➤</button>
    </div>
  </div>
</div>


Solution

  • I have only changed the JS part and added .collapsed CSS class. Comments are in the code.

    const chatLauncher = document.getElementById('chatLauncher');
    const chatContainer = document.getElementById('chatContainer');
    const sidebar = document.getElementById('sidebar');
    
    // just changed the name
    function closeChat() {
      chatContainer.style.display = 'none';
      chatLauncher.style.display = 'flex';
    }
    
    chatLauncher.addEventListener('click', () => {
      chatContainer.style.display = 'flex';
      chatLauncher.style.display = 'none';
      
      // when opening the chat, it should not be fullscreen
      chatContainer.classList.remove('fullscreen');
      // with collapsed sidebar
      sidebar.querySelector('.content').style.display = 'none';
      
      // this is not needed because you don't have 
      // the option to close chat when sidebar is fullwidth
      // in case you implment it later
      // sidebar.classList.remove('fullwidth');
    });
    
    function toggleFullscreen() {
      chatContainer.classList.toggle('fullscreen');
      
      // also toggle sidebar
      if (chatContainer.classList.contains('fullscreen')) {
        sidebar.querySelector('.content').style.display = 'block';
      } else {
        sidebar.querySelector('.content').style.display = 'none';
        sidebar.classList.remove('collapsed');
      }
    }
    
    function toggleSidebar() {
      const isFullscreen = chatContainer.classList.contains('fullscreen');
      // isMobile is always false if isFullscreen is true
      // isFullscreen = !isMobile
      // const isMobile = chatContainer.offsetWidth <= 400;
    
      if (!isFullscreen) {
        sidebar.classList.toggle('fullwidth');
      } else {
        sidebar.classList.toggle('collapsed');
      }
      
      sidebar.querySelector('.content').style.display =
        sidebar.querySelector('.content').style.display == 'block' ? 'none' : 'block';
    }
    /* added the following */
    .collapsed {
      width: 60px !important;
    }
    
    * {
      box-sizing: border-box;
    }
    
    body {
      margin: 0;
      font-family: 'Segoe UI', sans-serif;
      background: #f3f3f3;
    }
    
    /* ---------- launcher ---------- */
    .chat-launcher {
      position: fixed;
      bottom: 20px;
      right: 20px;
      background: #000;
      color: #fff;
      border-radius: 50%;
      width: 48px;
      height: 48px;
      display: flex;
      align-items: center;
      justify-content: center;
      box-shadow: 0 2px 10px rgba(0, 0, 0, 0.3);
      cursor: pointer;
      z-index: 1000;
    }
    
    /* ---------- chat container ---------- */
    .chat-container {
      display: none;
      height: 600px;
      width: 400px;
      max-width: 90vw;
      position: fixed;
      bottom: 80px;
      right: 20px;
      background: #fff;
      box-shadow: 0 0 12px rgba(0, 0, 0, 0.15);
      border-radius: 12px;
      overflow: hidden;
      z-index: 1001;
      transition: all .3s ease;
    }
    
    /* ---------- fullscreen overrides ---------- */
    .chat-container.fullscreen {
      width: 100vw;
      height: 100vh;
      bottom: 0;
      right: 0;
      border-radius: 0;
      display: flex;
      flex-direction: row;
    }
    
    /* sidebar in fullscreen */
    .chat-container.fullscreen .sidebar {
      width: 250px;
      border-right: 1px solid #ddd;
    }
    
    .chat-container.fullscreen .sidebar .content {
      display: block;
    }
    
    /* chat area in fullscreen */
    .chat-container.fullscreen .container {
      display: flex;
      flex: 1 1 auto;
    }
    
    /* ---------- sidebar ---------- */
    .sidebar {
      width: 60px;
      background: #fff;
      border-right: 1px solid #ddd;
      padding: 20px;
      transition: width .3s;
      flex-shrink: 0;
    }
    
    .sidebar .toggle-btn {
      font-size: 20px;
      cursor: pointer;
      margin-bottom: 20px;
    }
    
    .sidebar .content {
      display: none;
    }
    
    .sidebar.fullwidth {
      width: 100%;
      border-right: none;
    }
    
    .sidebar.fullwidth .content {
      display: block;
    }
    
    .sidebar.fullwidth~.container {
      display: none;
    }
    
    /* ---------- chat area ---------- */
    .container {
      flex: 1;
      display: flex;
      flex-direction: column;
      overflow: hidden;
      min-width: 0;
    }
    
    .header {
      background: #f5f5f5;
      padding: 10px 16px;
      display: flex;
      align-items: center;
      justify-content: space-between;
    }
    
    .header h2 {
      flex: 1;
      text-align: center;
      font-size: 18px;
      margin: 0;
    }
    
    .header .icons {
      display: flex;
      gap: 10px;
      font-size: 20px;
      color: #333;
      cursor: pointer;
    }
    
    .blue-banner {
      background: linear-gradient(to right, #2979ff, #1976d2);
      color: white;
      padding: 15px;
      margin: 10px;
      border-radius: 10px;
      display: flex;
      align-items: center;
      gap: 10px;
      font-size: 14px;
    }
    
    .messages {
      flex: 1;
      padding: 20px;
      overflow-y: auto;
    }
    
    .message {
      margin-bottom: 20px;
    }
    
    .message.bot {
      background: #fff;
      border-radius: 10px;
      padding: 15px;
      box-shadow: 0 0 4px rgba(0, 0, 0, .1);
      max-width: 80%;
    }
    
    .message.user {
      text-align: right;
    }
    
    .message.user .bubble {
      display: inline-block;
      background: #1976d2;
      color: white;
      border-radius: 20px;
      padding: 10px 20px;
    }
    
    .timestamp {
      font-size: 12px;
      color: gray;
      margin-top: 5px;
    }
    
    .input-area {
      display: flex;
      align-items: center;
      padding: 10px;
      background: white;
      border-top: 1px solid #ccc;
    }
    
    .input-area input {
      flex: 1;
      padding: 10px;
      border: 1px solid #ccc;
      border-radius: 20px;
      outline: none;
    }
    
    .input-area button {
      background: #1976d2;
      color: white;
      border: none;
      border-radius: 50%;
      padding: 10px 15px;
      margin-left: 10px;
      cursor: pointer;
    }
    
    .upload-btn {
      margin-right: 10px;
      font-size: 12px;
      color: #1976d2;
      cursor: pointer;
    }
    <div class="chat-launcher" id="chatLauncher">💬</div>
    
    <div class="chat-container" id="chatContainer">
      <!-- sidebar -->
      <div class="sidebar" id="sidebar">
        <div class="toggle-btn" onclick="toggleSidebar()">☰</div>
        <div class="content">
          <h2>{nameHere}</h2>
          <p>{descriptionHere}</p>
          <h3>Continue Conversations</h3>
          <button style="padding:10px;border:1px solid #1976d2;border-radius:10px;width:100%;margin-bottom:10px;background:#E3F2FD;color:#000;">Sender: Clickable →</button>
          <h3>Talk to our experts</h3>
          <button style="padding:10px;width:100%;margin-bottom:10px;background:#F3E5F5;border:1px solid #CCC;border-radius:10px;">👨‍💼 Support</button>
          <div style="padding: 10px; border-radius: 10px; background: linear-gradient(to right, #d1c4e9, #f8bbd0);">
            <p><strong>Need specialized help?</strong><br/>Our teams are ready to assist you with any questions</p>
            <button style="padding: 5px 10px; background: blue; color: white; border: none; border-radius: 5px;">Call Us</button>
          </div>
        </div>
      </div>
    
      <!-- chat -->
      <div class="container">
        <div class="header">
          <div class="icons" onclick="closeChat()">✖</div>
          <h2>Support</h2>
          <div class="icons">
            <span onclick="alert('Call Clicked')">📞</span>
            <span onclick="toggleFullscreen()">⤢</span>
          </div>
        </div>
        <div class="blue-banner">
          📄
          <div>
            <strong>Enter your details</strong><br>
            <small>Click here to provide your information</small>
          </div>
        </div>
        <div class="messages">
          <div class="message bot">
            Hey 😃 How can I assist you with services today? Could you please share your username to help you better?
            <ul>
              <li>1. I have an issue with SMS</li>
              <li>2. I need help with Email</li>
              <li>3. Other service query</li>
            </ul>
            <div class="timestamp">10:26 am</div>
          </div>
          <div class="message user">
            <div class="bubble">hey</div>
            <div class="timestamp">10:26 am</div>
          </div>
          <div class="message bot">
            Hey 😃 How can I help you with today? Please share your username so I can assist you better.
            <ul>
              <li>1. I have an issue with SMS</li>
              <li>2. I need help with Email</li>
              <li>3. Other service query</li>
            </ul>
            <div class="timestamp">10:27 am</div>
          </div>
        </div>
        <div class="input-area">
          <span class="upload-btn">📎 Upload Files</span>
          <input type="text" placeholder="Message AI Assistant...">
          <button>➤</button>
        </div>
      </div>
    </div>