title: Dash-Plotly-bootstrap: How to design layout using dash bootstrap components?
body: <p>This Question is continous from what Tim Dunn asking in this <a href="https://stackoverflow.com/questions/63592900/plotly-dash-how-to-design-the-layout-using-dash-bootstrap-components/63650724#63650724">question</a>.</p>
  <p>@<a href="https://stackoverflow.com/users/10457843/kristian-haga">Kristian Haga</a> already answer  it. but I want to continue asking in answer section, it's forbidden by @<a href="https://stackoverflow.com//users/4099593/bhargav-rao">Bhargav-rao</a>.</p>
  <p>He ask me to make the new one and really sure, someone will answer it.</p>
  <p>to make everybody understood I copy and paste the Tim Dunn question and Khristian Haga answer here.</p>
  <p>Tim dunn asking how to make layout in dash like <a href="https://i.stack.imgur.com/MNz5W.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/MNz5W.png" alt="this" /></a>:</p>
  <p>a full dashboard with full graph with some layout configuration.</p>
  <p>@Kristian Haga already answer it by this script:</p>
  <pre><code>import plotly.express as px
  from jupyter_dash import JupyterDash
  import dash_core_components as dcc
  import dash_html_components as html
  import dash_bootstrap_components as dbc
  from dash.dependencies import Input, Output
  import plotly.express as px
  
  # Iris bar figure
  def drawFigure():
      return  html.Div([
          dbc.Card(
              dbc.CardBody([
                  dcc.Graph(
                      figure=px.bar(
                          df, x=&quot;sepal_width&quot;, y=&quot;sepal_length&quot;, color=&quot;species&quot;
                      ).update_layout(
                          template='plotly_dark',
                          plot_bgcolor= 'rgba(0, 0, 0, 0)',
                          paper_bgcolor= 'rgba(0, 0, 0, 0)',
                      ),
                      config={
                          'displayModeBar': False
                      }
                  ) 
              ])
          ),  
      ])
  
  # Text field
  def drawText():
      return html.Div([
          dbc.Card(
              dbc.CardBody([
                  html.Div([
                      html.H2(&quot;Text&quot;),
                  ], style={'textAlign': 'center'}) 
              ])
          ),
      ])
  
  # Data
  df = px.data.iris()
  
  # Build App
  app = JupyterDash(external_stylesheets=[dbc.themes.SLATE])
  
  app.layout = html.Div([
      dbc.Card(
          dbc.CardBody([
              dbc.Row([
                  dbc.Col([
                      drawText()
                  ], width=3),
                  dbc.Col([
                      drawText()
                  ], width=3),
                  dbc.Col([
                      drawText()
                  ], width=3),
                  dbc.Col([
                      drawText()
                  ], width=3),
              ], align='center'), 
              html.Br(),
              dbc.Row([
                  dbc.Col([
                      drawFigure() 
                  ], width=3),
                  dbc.Col([
                      drawFigure()
                  ], width=3),
                  dbc.Col([
                      drawFigure() 
                  ], width=6),
              ], align='center'), 
              html.Br(),
              dbc.Row([
                  dbc.Col([
                      drawFigure()
                  ], width=9),
                  dbc.Col([
                      drawFigure()
                  ], width=3),
              ], align='center'),      
          ]), color = 'dark'
      )
  ])
  
  # Run app and display result inline in the notebook
  app.run_server(mode='external')
  </code></pre>
  <p>the result will be like this <a href="https://i.stack.imgur.com/KEm4K.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/KEm4K.png" alt="this" /></a>:</p>
  <p>so, I just continue the question by adding more question. more step</p>
  <p>if i want make something like this...</p>
  <p><a href="https://i.stack.imgur.com/ajaSy.jpg" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/ajaSy.jpg" alt="enter image description here" /></a></p>
  <p>how to do that...? sorry if the picture is awfull, i make it, in rush...</p>
  <p>the different is:</p>
  <ol>
  <li>layout, i put a text top of every graph, but with a column section that separated it in to 2 section rows</li>
  <li>how if one of the content is a map?</li>
  <li>how if under all the content and the map and the text, there is a layer, with a transparent color.</li>
  <li>how to create sidebar</li>
  <li>how to make the title change if we press a button</li>
  </ol>
  <p>any data, can be use it to explain...
  like what @<a href="https://stackoverflow.com/users/10457843/kristian-haga">Khristian Haga</a> do, he use open source database.</p>
  <p>several question I already found it and I put here to explain:</p>
  <p>base on the clue in <a href="https://dash-bootstrap-components.opensource.faculty.ai/examples/simple-sidebar/" rel="nofollow noreferrer">here</a>:</p>
  <p>i make a script like this:</p>
  <p>first i make a css file and save it inside the assets folder, the file contain script like this:</p>
  <pre><code>html {
    height: 100%;}
  body{
    margin:0;
    width:100%;
    height:100%;
    background-image: url(&quot;./backgroud1.png&quot;);
    background-size: cover;
    background-position: center;}
  </code></pre>
  <p>then i write a script like this:</p>
  <p>EDIT:
  because 80% of my question already answered, I put the answer here.
  and several things that I explain before, I cut it, because of limitation of the character.</p>
  <p>base on my self question and my answer on <a href="https://stackoverflow.com/questions/63678461">here</a>, yeah sad i think...</p>
  <p>i can make something like this:
  <a href="https://i.stack.imgur.com/B0vwx.jpg" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/B0vwx.jpg" alt="enter image description here" /></a></p>
  <p>if i do something, with the dropdown and press button, it will become like this:
  <a href="https://i.stack.imgur.com/ZGkr5.jpg" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/ZGkr5.jpg" alt="enter image description here" /></a></p>
  <p>now, the last step is put text and image on the layer, and change in the same time when I press the button. but i still don't know how to do that right now. but to make layout like the image above, this is the script.</p>
  <pre><code>import dash
  import dash_core_components as dcc
  import dash_html_components as html
  from plotly import graph_objs as go
  import dash_bootstrap_components as dbc
  import plotly.express as px
  from dash.dependencies import Input, Output, State
  import pandas as pd
  
  # this is the data of the city
  data = [['a','b','d','h'],
         ['a','b','d','i'],
         ['a','b','e','j'],
         ['a','b','e','k'],
         ['a','c','f','l'],
         ['a','c','f','m'],
         ['a','c','g','n'],
         ['a','c','g','o'],
         ['z','x','p','a1'],
         ['z','x','p','a2'],
         ['z','x','q','a3'],
         ['z','x','q','a4'],
         ['z','y','r','a5'],
         ['z','y','r','a6'],
         ['z','y','s','a7'],
         ['z','y','s','a8']]
  
  df = pd.DataFrame(data)
  df.columns = ['city', 'district', 'area', 'subarea']
  
  city_list = list(set(df['city'].to_list()))
  city_list.insert(0,'all city')
  
  #function to help  typing code more shorter in the changing title section
  # subarea
  # ===============
  def search_area_from_subarea(area_name):
      area_level = list(set(df[df.loc[:, 'subarea'] == area_name]['area'].to_list()))[0]
      return area_level
  
  def search_district_from_subarea(area_name):
      area_level = list(set(df[df.loc[:, 'subarea'] == area_name]['district'].to_list()))[0]
      return area_level
  
  def search_city_from_subarea(area_name):
      area_level = list(set(df[df.loc[:, 'subarea'] == area_name]['city'].to_list()))[0]
      return area_level
  
  # area
  # ===============
  def search_district_from_area(area_name):
      area_level = list(set(df[df.loc[:, 'area'] == area_name]['district'].to_list()))[0]
      return area_level
  
  def search_city_from_area(area_name):
      area_level = list(set(df[df.loc[:, 'area'] == area_name]['city'].to_list()))[0]
      return area_level
  
  # district
  # ============
  def search_city_from_district(area_name):
      area_level = list(set(df[df.loc[:, 'district'] == area_name]['city'].to_list()))[0]
      return area_level
  
  layer1 = html.Div([
          dbc.Col([
              html.Hr(),
              # top side
              # for title text
              dbc.Row([],id='left_side1',
               style={
              'margin-top': '-4px',
              'margin-left': '0px',
              'width': '609px',
              'height': '36px',
              'backgroundColor': 'rgba(120,0,0,0.4)'
              }
                        ),
              # for graph, etc
              dbc.Row([],id='left_side2', 
               style={
              'margin-top': '5px',
              'margin-left': '0px',
              'width': '609px',
              'height': '215px',
              'backgroundColor': 'rgba(120,0,0,0.4)'
              }
                        ),
              #middle
              # for title text
              dbc.Row([],id='left_side3',
              style={
              'margin-top': '9px',
              'margin-left': '0px',
              'width': '314px',
              'height': '36px',
              'backgroundColor': 'rgba(0,0,50,0.4)'
              }
                        ),
              # for graph, etc
              dbc.Row([],id='left_side4',
              style={
              'margin-top': '5px',
              'margin-left': '0px',
              'width': '314px',
              'height': '215px',
              'backgroundColor': 'rgba(0,0,50,0.4)'
              }
                        ),
              #bawah
              # for title text
              dbc.Row([],id='left_side5',
              style={
              'margin-top': '9px',
              'margin-left': '0px',
              'width': '609px',
              'height': '36px',
              'backgroundColor': 'rgba(0,0,120,0.4)'
              }
                        ),
              # for graph, etc
              dbc.Row([],id='left_side6',
              style={
              'margin-top': '5px',
              'margin-left': '0px',
              'width': '609px',
              'height': '215px',
              'backgroundColor': 'rgba(0,0,120,0.4)'
              }
                        ),
          ])
  ])
  
  layer2 = html.Div([
      html.Hr(),
      #  for title text
      dbc.Col([
              dbc.Row([],id='mid_side1',
              style={
              'margin-top': '-540px',
              'margin-left': '330px',
              'width': '609px',
              'height': '36px',
              'backgroundColor': 'rgba(0,120,0,0.4)'
              }
                        ),
      # for graph, etc
      dbc.Row([],id='mid_side2',
      style={
      'margin-top': '5px',
      'margin-left': '330px',
      'width': '609px',
      'height': '215px',
      'backgroundColor': 'rgba(0,120,0,0.4)'
      }
                ),
       # for title text
      
              dbc.Row([],id='mid_side3',
              style={
              'margin-top': '9px',
              'margin-left': '625px',
              'width': '609px',
              'height': '36px',
              'backgroundColor': 'rgba(120,0,120,0.4)'
              }
                        ),
      # for graph, etc
      dbc.Row([],id='mid_side4',
      style={
      'margin-top': '5px',
      'margin-left': '625px',
      'width': '609px',
      'height': '215px',
      'backgroundColor': 'rgba(120,0,120,0.4)'
      }
                )
              ])
          ])
  
  layer3 = html.Div([
      html.Hr(),
      # for title text
      dbc.Col([
              dbc.Row([],id='right_side1',
              style={
              'margin-top': '-548px',
              'margin-left': '957px',
              'width': '579px',
              'height': '36px',
              'backgroundColor': 'rgba(0,120,120,0.4)'
              }
                        ),
      # for graph, etc
      dbc.Row([],id='right_side2',
      style={
      'margin-top': '5px',
      'margin-left': '957px',
      'width': '579px',
      'height': '215px',
      'backgroundColor': 'rgba(0,120,120,0.4)'
      }
                ),
       # for title text
      
              dbc.Row([],id='right_side3',
              style={
              'margin-top': '9px',
              'margin-left': '1251px',
              'width': '285px',
              'height': '36px',
              'backgroundColor': 'rgba(50,120,0,0.4)'
              }
                        ),
      # for graph, etc
      dbc.Row([],id='right_side4',
      style={
      'margin-top': '5px',
      'margin-left': '1251px',
      'width': '285px',
      'height': '215px',
      'backgroundColor': 'rgba(50,120,0,0.4)'
      }
                )
              ])
          ])
  
  layer4 = html.Div([])
  
  layer_boxes = html.Div([
      layer1,
      layer2,
      layer3,
      layer4],
        style={
              'margin-top': '0px',
              'margin-left': '323px',
              'width': '1568px',
              'height': '813px',
              'backgroundColor': 'rgba(0,0,0,0.3)'
              }
                        )
  
  SIDEBAR_STYLE = {
                    &quot;position&quot;: &quot;fixed&quot;,
                    &quot;top&quot;: '-15px',
                    &quot;left&quot;: '0',
                    &quot;bottom&quot;: '0',
                    &quot;width&quot;: &quot;16rem&quot;,
                    &quot;height&quot;: &quot;100%&quot;,
                    &quot;padding&quot;: &quot;2rem 1rem&quot;,
                    &quot;background-color&quot;: &quot;rgba(0, 0, 0, 0.2)&quot;,
                    'align': 'center'
                    }
  app = dash.Dash()
  app.layout= html.Div([
     
     dbc.Nav(
         [html.Div([html.Img(src='https://www.gravatar.com/avatar/f2d20dc48eff4d12e2352d39018a41af?s=48&amp;d=identicon&amp;r=PG&amp;f=1') 
               ],style={'height':'100px', 
                          'width':'100px',
                          'margin-top': '-6px',
                          'margin-left': '97px'}),
          dcc.Dropdown(
               id='menu_city', clearable=False,
               value='all city', options=[
               {'label': c1, 'value': c1}
               for c1 in city_list]),
  
            dcc.Dropdown(
               id='menu_district', clearable=False,
               value='all district'),
              dcc.Dropdown(
               id='menu_area', clearable=False,
               value='all area'),
                  dcc.Dropdown(
               id='menu_subarea', clearable=False,
               value='all subarea'),
             html.Hr(),
             dbc.Button(id='button_show',children=&quot;SHOW DATA&quot;, color=&quot;info&quot;, className=&quot;mr-1&quot;)
           ],style=SIDEBAR_STYLE )
       , html.Div([
          dbc.Row(
              dbc.Col([
                  html.H3(id='title_for_test')],
                  align='right', width={'size': '10', 
                                        'offset': '2',}, style={'margin-left': '323px',
                                                                'margin-top': '-9px',
                                                                'color': 'rgb(255,255,255)',
                                                                'fontSize': '22px',
                                                                'height' : '100%'}
              )
                ),
           layer_boxes
             ])
        ])
  
  
  
  # =================================
  # confifuration to set district dropdown menu change base selection on city dropdown menu
  @app.callback(dash.dependencies.Output('menu_district','options'),
                [Input('menu_city', 'value')])
                
  def set_list(selected_options):
      if selected_options == 'all city':
          temp_list = list(set(df['district'].to_list()))
          temp_list.insert(0, 'all district')
          return [{'label': i, 'value': i} for i in temp_list]
      else:
          temp_list = list(set(df[df.loc[:,'city'] == selected_options]['district'].to_list()))
          temp_list.insert(0, 'all district')
          return [{'label': i, 'value': i} for i in temp_list]
  # -----------------------------
  # configuration to prevent district dropdown menu error
  @app.callback(dash.dependencies.Output('menu_district','value'),
                [Input('menu_district', 'options')])
                
  def set_list(selected_options):
      return selected_options[0]['value']
  
  
  
  
  # =======================================
  # confifuration to set area dropdown menu change base selection on district dropdown menu
  
  @app.callback(dash.dependencies.Output('menu_area','options'),
                [Input('menu_city', 'value')],
                [Input('menu_district', 'value')],
               multi = True)
                
  def set_list(selected_options1, selected_options2):
      # 2 input, means: 2**2 possibility
      #print('1',selected_options1)
      #print('2', selected_options2)
      
      if selected_options1 == 'all city' and selected_options2 == 'all district':
          temp_list = list(set(df['area'].to_list()))
          temp_list.insert(0, 'all area')
          return [{'label': i, 'value': i} for i in temp_list]
      
      if selected_options1 != 'all city' and selected_options2 == 'all district':
          temp_list = list(set(df[(df.loc[:,'district'] == selected_options2)]['area'].to_list()))
          temp_list.insert(0, 'all area')
          return [{'label': i, 'value': i} for i in temp_list]
      
      if selected_options1 == 'all city' and selected_options2 != 'all district':
          temp_list = list(set(df[(df.loc[:,'district'] == selected_options2)]['area'].to_list()))
          temp_list.insert(0, 'all area')
          return [{'label': i, 'value': i} for i in temp_list]
      
      if selected_options1 != 'all city' and selected_options2 != 'all district':
          temp_list = list(set(df[(df.loc[:,'city'] == selected_options1) &amp; (df.loc[:,'district'] == selected_options2)]['area'].to_list()))
          temp_list.insert(0, 'all area')
          return [{'label': i, 'value': i} for i in temp_list]
      
  # -----------------------------
  # configuration to prevent area dropdown menu error
  
  @app.callback(dash.dependencies.Output('menu_area','value'),
                [Input('menu_area', 'options')])
  
  
  
  
  # ========================================
  # confifuration to set subarea dropdown menu change base selection on area dropdown menu
  
  @app.callback(dash.dependencies.Output('menu_subarea','options'),
                [Input('menu_city', 'value')],
                [Input('menu_district', 'value')],
                [Input('menu_area', 'value')],
                multi=True
               )
                
  def set_list(selected_options1,selected_options2, selected_options3):
      # 3 input = 2**3 possibility
      
      # possibility 1:
      if selected_options1 == 'all city' and selected_options2 == 'all district' and selected_options3 == 'all area':
          temp_list = list(set(df['subarea'].to_list()))
          temp_list.insert(0, 'all subarea')
          return [{'label': i, 'value': i} for i in temp_list]
      
      # possibility 2:
      if selected_options1 == 'all city' and selected_options2 == 'all district' and selected_options3 != 'all area':
          temp_list = list(set(df[(df.loc[:,'area'] == selected_options3)]['subarea'].to_list()))
          temp_list.insert(0, 'all subarea')
          return [{'label': i, 'value': i} for i in temp_list]
      # possibility 3:
      if selected_options1 == 'all city' and selected_options2 != 'all district' and selected_options3 == 'all area':
          temp_list = list(set(df[(df.loc[:,'district'] == selected_options2)]['subarea'].to_list()))
          temp_list.insert(0, 'all subarea')
          return [{'label': i, 'value': i} for i in temp_list]
      # possibility 4:
      if selected_options1 != 'all city' and selected_options2 == 'all district' and selected_options3 == 'all area':
          temp_list = list(set(df[(df.loc[:,'city'] == selected_options1)]['subarea'].to_list()))
          temp_list.insert(0, 'all subarea')
          return [{'label': i, 'value': i} for i in temp_list]
      
      
      # possibility 5:
      if selected_options1 != 'all city' and selected_options2 != 'all district' and selected_options3 == 'all area':
          temp_list = list(set(df[(df.loc[:,'city'] == selected_options1) &amp; (df.loc[:,'district'] == selected_options2)]['subarea'].to_list()))
          temp_list.insert(0, 'all subarea')
          return [{'label': i, 'value': i} for i in temp_list]
      
      # possibility 6:
      if selected_options1 != 'all city' and selected_options2 == 'all district' and selected_options3 != 'all area':
          temp_list = list(set(df[(df.loc[:,'city'] == selected_options1) &amp; (df.loc[:,'area'] == selected_options3)]['subarea'].to_list()))
          temp_list.insert(0, 'all subarea')
          return [{'label': i, 'value': i} for i in temp_list]
      
      # possibility 7:
      if selected_options1 == 'all city' and selected_options2 != 'all district' and selected_options3 != 'all area':
          temp_list = list(set(df[(df.loc[:,'district'] == selected_options2) &amp; (df.loc[:,'area'] == selected_options3)]['subarea'].to_list()))
          temp_list.insert(0, 'all subarea')
          return [{'label': i, 'value': i} for i in temp_list]
      
      # possibility 8:
      if selected_options1 != 'all city' and selected_options2 != 'all district' and selected_options3 != 'all area':
          temp_list = list(set(df[(df.loc[:,'city'] == selected_options1) &amp; (df.loc[:,'district'] == selected_options2) &amp; (df.loc[:,'area'] == selected_options3)]['subarea'].to_list()))
          temp_list.insert(0, 'all subarea')
          return [{'label': i, 'value': i} for i in temp_list]
      
      
  # -----------------------------
  # configuration to prevent subarea dropdown menu error
  @app.callback(dash.dependencies.Output('menu_subarea','value'),
                [Input('menu_subarea', 'options')])
  
  def set_list(selected_options):
      return selected_options[0]['value']
  
  
  #configuration callback button
  @app.callback(dash.dependencies.Output('title_for_test','children'),
                [Input('button_show', 'n_clicks' )],
                [State('menu_city', 'value')],
                [State('menu_district', 'value')],
                [State('menu_area', 'value')],
                [State('menu_subarea', 'value')],
               multi=True)
  
  def eksekusi(n_clicks, number1, number2, number3, number4):
      
      
      # provinsi
      if number1 == 'all city' and number2 == 'all district' and number3 == 'all area' and number4 == 'all subarea':
          return 'DEMOGRAFIC DATA OF MY STATE'
      
      
      # city / city
      if number1 != 'all city' and number2 == 'all district' and number3 == 'all area' and number4 == 'all subarea':
          return 'DEMOGRAFIC DATA OF ' + number1 + ' CITY'
          
          
      # district    
      if (number1 == 'all city' or number1 != 'all city') and number2 != 'all district' and number3 == 'all area' and number4 == 'all subarea':
          return 'DEMOGRAFIC DATA DISTRICT ' + number2 + ', CITY ' + search_city_from_district(number2)
  
  
      # area
      if (number1 == 'all city' or number1 != 'all city') and (number2 == 'all district' or number2 != 'all district') and number3  != 'all area' and number4 == 'all subarea':
          return 'DEMOGRAFIC DATA AREA ' + number3 ,html.Br(), 'DISTRICT ' + search_district_from_area(number3) +  ', CITY ' + search_city_from_area(number3)
  
      # subarea
      if (number1 == 'all city' or number1 != 'all city') and (number2 != 'all district' or number2 == 'all district') and (number3  != 'all area' or number3  == 'all area') and number4 != 'all subarea':
          return 'DEMOGRAFIC DATA SUBAREA ' + number4 + ', AREA ' + search_area_from_subarea(number4),html.Br(),'DISTRICT ' + search_district_from_subarea(number4) + ', CITY ' + search_city_from_subarea(number4)
  
  
  if __name__ == &quot;__main__&quot;:
      app.run_server(host='127.0.0.1', port='8051')
  </code></pre>
  <p>NOTE:
  because of the limitation of the characters, i delete what I already type before...</p>
  <p>especially about drive you element manually like play a game (with keyboard), until you feel it's already in the right place, after that, view the perimeter, then copy it to your script.</p>
  <p>it's play it, in inspect element (one of options menu that shown, when you right click the browser). by the way, i'm not delete the picture, i preview it below. hope you can imagine it.</p>
  <p>next time if i already know how to callback the press button to change the graph in dashboard, i will post in answer section.
  here the picture that i used to explain some step that i already edit / delete because of limitation from stackoverflow.com.
  copy format style
  <a href="https://i.stack.imgur.com/Q8aaw.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/Q8aaw.png" alt="image1" /></a>
  edit by yourself, a helper menu will show
  <a href="https://i.stack.imgur.com/kBEa5.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/kBEa5.png" alt="image2" /></a></p>
  <p>double-click the number after typing, raise or decrease the number value with up / down arrow from keyboard, the element will move, or change, base on raised / decreased value. after you feel match with your taste, see the value, copy to your code. that the easy way you set your code value.</p>
  <p>so this is the list of my question that already answer.</p>
  <ol>
  <li>layout, i put a text top of every graph, but with a column section that separated it in to 2 section rows.  ANSWERED</li>
  <li>how if one of the content is a map? ANSWERED</li>
  <li>how if under all the content and the map and the text, there is a layer, with a transparent color. ANSWERED</li>
  <li>how to create sidebar. ANSWRED</li>
  <li>how to make the title change if we press a button. ANSWERED.</li>
  </ol>
  <p>new question:</p>
  <ol start="6">
  <li>how to make not only title change, but the graph change to after press the button. because, multioutput of the callback is not easy to handle.</li>
  </ol>