diff --git a/demo/src/pages/badge/mod.rs b/demo/src/pages/badge/mod.rs
index 60b5924..a45d93b 100644
--- a/demo/src/pages/badge/mod.rs
+++ b/demo/src/pages/badge/mod.rs
@@ -107,6 +107,12 @@ pub fn BadgePage() -> impl IntoView {
                         <td></td>
                         <td>"Badge's content."</td>
                     </tr>
+                    <tr>
+                        <td>"class"</td>
+                        <td>"MaybeSignal<String>"</td>
+                        <td>"Default::default()"</td>
+                        <td>"Addtional classes for the badge element."</td>
+                    </tr>
                 </tbody>
             </Table>
         </div>
diff --git a/demo/src/pages/breadcrumb/mod.rs b/demo/src/pages/breadcrumb/mod.rs
index e347d8c..98870e6 100644
--- a/demo/src/pages/breadcrumb/mod.rs
+++ b/demo/src/pages/breadcrumb/mod.rs
@@ -86,6 +86,12 @@ pub fn BreadcrumbPage() -> impl IntoView {
                         <td></td>
                         <td>"Breadcrumb's content."</td>
                     </tr>
+                    <tr>
+                        <td>"class"</td>
+                        <td>"MaybeSignal<String>"</td>
+                        <td>"Default::default()"</td>
+                        <td>"Addtional classes for the breadcrumb element."</td>
+                    </tr>
                 </tbody>
             </Table>
             <h3>"BreadcrumbItem Props"</h3>
@@ -105,6 +111,12 @@ pub fn BreadcrumbPage() -> impl IntoView {
                         <td></td>
                         <td>"BreadcrumbItem's content."</td>
                     </tr>
+                    <tr>
+                        <td>"class"</td>
+                        <td>"MaybeSignal<String>"</td>
+                        <td>"Default::default()"</td>
+                        <td>"Addtional classes for the breadcrumb link element."</td>
+                    </tr>
                 </tbody>
             </Table>
         </div>
diff --git a/demo/src/pages/calendar/mod.rs b/demo/src/pages/calendar/mod.rs
index 595a9c2..a256d34 100644
--- a/demo/src/pages/calendar/mod.rs
+++ b/demo/src/pages/calendar/mod.rs
@@ -50,6 +50,12 @@ pub fn CalendarPage() -> impl IntoView {
                         </td>
                         <td></td>
                     </tr>
+                    <tr>
+                        <td>"class"</td>
+                        <td>"MaybeSignal<String>"</td>
+                        <td>"Default::default()"</td>
+                        <td>"Addtional classes for the calendar element."</td>
+                    </tr>
                 </tbody>
             </Table>
         </div>
diff --git a/demo/src/pages/card/mod.rs b/demo/src/pages/card/mod.rs
index 276fb3e..98a6b7c 100644
--- a/demo/src/pages/card/mod.rs
+++ b/demo/src/pages/card/mod.rs
@@ -84,6 +84,12 @@ pub fn CardPage() -> impl IntoView {
                         <td></td>
                         <td>"Card's content."</td>
                     </tr>
+                    <tr>
+                        <td>"class"</td>
+                        <td>"MaybeSignal<String>"</td>
+                        <td>"Default::default()"</td>
+                        <td>"Addtional classes for the card element."</td>
+                    </tr>
                 </tbody>
             </Table>
             <h3>"Card Slots"</h3>
diff --git a/demo/src/pages/checkbox/mod.rs b/demo/src/pages/checkbox/mod.rs
index 1fb699c..957d91a 100644
--- a/demo/src/pages/checkbox/mod.rs
+++ b/demo/src/pages/checkbox/mod.rs
@@ -106,6 +106,12 @@ pub fn CheckboxPage() -> impl IntoView {
                         <td></td>
                         <td>"CheckboxGroup's content."</td>
                     </tr>
+                    <tr>
+                        <td>"class"</td>
+                        <td>"MaybeSignal<String>"</td>
+                        <td>"Default::default()"</td>
+                        <td>"Addtional classes for the checkbox element."</td>
+                    </tr>
                 </tbody>
             </Table>
             <h3>"CheckboxItem Props"</h3>
diff --git a/demo/src/pages/color_picker/mod.rs b/demo/src/pages/color_picker/mod.rs
index 257bcd3..ff9ec57 100644
--- a/demo/src/pages/color_picker/mod.rs
+++ b/demo/src/pages/color_picker/mod.rs
@@ -44,6 +44,12 @@ pub fn ColorPickerPage() -> impl IntoView {
                         <td>"RwSignal<RGBA>"</td>
                         <td>"Value of the picker."</td>
                     </tr>
+                    <tr>
+                        <td>"class"</td>
+                        <td>"MaybeSignal<String>"</td>
+                        <td>"Default::default()"</td>
+                        <td>"Addtional classes for the color picker element."</td>
+                    </tr>
                 </tbody>
             </Table>
         </div>
diff --git a/demo/src/pages/divider/mod.rs b/demo/src/pages/divider/mod.rs
index f588e51..e0eb907 100644
--- a/demo/src/pages/divider/mod.rs
+++ b/demo/src/pages/divider/mod.rs
@@ -23,6 +23,25 @@ pub fn DividerPage() -> impl IntoView {
 
                 </DemoCode>
             </Demo>
+            <h3>"Divider Props"</h3>
+            <Table single_column=true>
+                <thead>
+                    <tr>
+                        <th>"Name"</th>
+                        <th>"Type"</th>
+                        <th>"Default"</th>
+                        <th>"Description"</th>
+                    </tr>
+                </thead>
+                <tbody>
+                    <tr>
+                        <td>"class"</td>
+                        <td>"MaybeSignal<String>"</td>
+                        <td>"Default::default()"</td>
+                        <td>"Addtional classes for the divider element."</td>
+                    </tr>
+                </tbody>
+            </Table>
         </div>
     }
 }
diff --git a/demo/src/pages/grid/mod.rs b/demo/src/pages/grid/mod.rs
index da508f2..1d809a1 100644
--- a/demo/src/pages/grid/mod.rs
+++ b/demo/src/pages/grid/mod.rs
@@ -142,6 +142,43 @@ pub fn GridPage() -> impl IntoView {
                         <td>"0"</td>
                         <td>"Vertical gap."</td>
                     </tr>
+                    <tr>
+                        <td>"class"</td>
+                        <td>"MaybeSignal<String>"</td>
+                        <td>"Default::default()"</td>
+                        <td>"Addtional classes for the grid element."</td>
+                    </tr>
+                </tbody>
+            </Table>
+            <h3>"GridItem Props"</h3>
+            <Table single_column=true>
+                <thead>
+                    <tr>
+                        <th>"Name"</th>
+                        <th>"Type"</th>
+                        <th>"Default"</th>
+                        <th>"Description"</th>
+                    </tr>
+                </thead>
+                <tbody>
+                    <tr>
+                        <td>"column"</td>
+                        <td>"MaybeSignal<u16>"</td>
+                        <td>"1"</td>
+                        <td>"Number of columns this grid item will occupy."</td>
+                    </tr>
+                    <tr>
+                        <td>"offset"</td>
+                        <td>"MaybeSignal<u16>"</td>
+                        <td>"0"</td>
+                        <td>"Horizontal offset."</td>
+                    </tr>
+                    <tr>
+                        <td>"class"</td>
+                        <td>"MaybeSignal<String>"</td>
+                        <td>"Default::default()"</td>
+                        <td>"Addtional classes for the grid item element."</td>
+                    </tr>
                 </tbody>
             </Table>
         </div>
diff --git a/demo/src/pages/image/mod.rs b/demo/src/pages/image/mod.rs
index 1b6e5a9..75c18ea 100644
--- a/demo/src/pages/image/mod.rs
+++ b/demo/src/pages/image/mod.rs
@@ -70,6 +70,12 @@ pub fn ImagePage() -> impl IntoView {
                         <td>"Default::default()"</td>
                         <td>"Object-fit type of the image in the container."</td>
                     </tr>
+                    <tr>
+                        <td>"class"</td>
+                        <td>"MaybeSignal<String>"</td>
+                        <td>"Default::default()"</td>
+                        <td>"Addtional classes for the image element."</td>
+                    </tr>
                 </tbody>
             </Table>
         </div>
diff --git a/demo/src/pages/input/mod.rs b/demo/src/pages/input/mod.rs
index 8641034..e3805f6 100644
--- a/demo/src/pages/input/mod.rs
+++ b/demo/src/pages/input/mod.rs
@@ -213,6 +213,12 @@ pub fn InputPage() -> impl IntoView {
                         <td>"None"</td>
                         <td>"Callback triggered when the input is blurred."</td>
                     </tr>
+                    <tr>
+                        <td>"class"</td>
+                        <td>"MaybeSignal<String>"</td>
+                        <td>"Default::default()"</td>
+                        <td>"Addtional classes for the input element."</td>
+                    </tr>
                 </tbody>
             </Table>
             <h3>"Input Slots"</h3>
diff --git a/demo/src/pages/input_number/mod.rs b/demo/src/pages/input_number/mod.rs
index a882411..db15093 100644
--- a/demo/src/pages/input_number/mod.rs
+++ b/demo/src/pages/input_number/mod.rs
@@ -108,6 +108,12 @@ pub fn InputNumberPage() -> impl IntoView {
                         <td>"false"</td>
                         <td>"Whether the input is invalid."</td>
                     </tr>
+                    <tr>
+                        <td>"class"</td>
+                        <td>"MaybeSignal<String>"</td>
+                        <td>"Default::default()"</td>
+                        <td>"Addtional classes for the input element."</td>
+                    </tr>
                 </tbody>
             </Table>
             <h3>"T impl"</h3>
diff --git a/demo/src/pages/menu/mod.rs b/demo/src/pages/menu/mod.rs
index f05c041..30f2387 100644
--- a/demo/src/pages/menu/mod.rs
+++ b/demo/src/pages/menu/mod.rs
@@ -15,9 +15,7 @@ pub fn MenuPage() -> impl IntoView {
                     <MenuItem key="o" label="or"/>
                 </Menu>
                 <DemoCode slot>
-
-                    {highlight_str!(
-                        r#"
+{highlight_str!( r#"
                         let value = create_rw_signal(String::from("o"));
                                 
                         <Menu value>
@@ -53,6 +51,12 @@ pub fn MenuPage() -> impl IntoView {
                         <td></td>
                         <td>"Menu's content."</td>
                     </tr>
+                    <tr>
+                        <td>"class"</td>
+                        <td>"MaybeSignal<String>"</td>
+                        <td>"Default::default()"</td>
+                        <td>"Addtional classes for the menu element."</td>
+                    </tr>
                 </tbody>
             </Table>
             <h3>"MenuGroup Props"</h3>
@@ -78,6 +82,12 @@ pub fn MenuPage() -> impl IntoView {
                         <td></td>
                         <td>"MenuGroup's content."</td>
                     </tr>
+                    <tr>
+                        <td>"class"</td>
+                        <td>"MaybeSignal<String>"</td>
+                        <td>"Default::default()"</td>
+                        <td>"Addtional classes for the menu group element."</td>
+                    </tr>
                 </tbody>
             </Table>
             <h3>"MenuItem Props"</h3>
@@ -103,6 +113,12 @@ pub fn MenuPage() -> impl IntoView {
                         <td>"Default::default()"</td>
                         <td>"The indentifier of the menu item."</td>
                     </tr>
+                    <tr>
+                        <td>"class"</td>
+                        <td>"MaybeSignal<String>"</td>
+                        <td>"Default::default()"</td>
+                        <td>"Addtional classes for the menu item element."</td>
+                    </tr>
                 </tbody>
             </Table>
         </div>
diff --git a/demo/src/pages/nav_bar/mod.rs b/demo/src/pages/nav_bar/mod.rs
index cf1652f..70e7735 100644
--- a/demo/src/pages/nav_bar/mod.rs
+++ b/demo/src/pages/nav_bar/mod.rs
@@ -89,6 +89,12 @@ pub fn NavBarPage() -> impl IntoView {
                             <td>"Default::default()"</td>
                             <td>"NavBar right click."</td>
                         </tr>
+                        <tr>
+                            <td>"class"</td>
+                            <td>"MaybeSignal<String>"</td>
+                            <td>"Default::default()"</td>
+                            <td>"Addtional classes for the NavBar element."</td>
+                        </tr>
                     </tbody>
                 </Table>
             </div>
diff --git a/demo/src/pages/radio/mod.rs b/demo/src/pages/radio/mod.rs
index bd031ae..e8711ff 100644
--- a/demo/src/pages/radio/mod.rs
+++ b/demo/src/pages/radio/mod.rs
@@ -51,6 +51,12 @@ pub fn RadioPage() -> impl IntoView {
                         <td></td>
                         <td>"Radio's content."</td>
                     </tr>
+                    <tr>
+                        <td>"class"</td>
+                        <td>"MaybeSignal<String>"</td>
+                        <td>"Default::default()"</td>
+                        <td>"Addtional classes for the radio element."</td>
+                    </tr>
                 </tbody>
             </Table>
         </div>
diff --git a/demo/src/pages/select/mod.rs b/demo/src/pages/select/mod.rs
index 61b9845..cfce1bf 100644
--- a/demo/src/pages/select/mod.rs
+++ b/demo/src/pages/select/mod.rs
@@ -56,6 +56,12 @@ pub fn SelectPage() -> impl IntoView {
                         <td>"vec![]"</td>
                         <td>"Options that can be selected."</td>
                     </tr>
+                    <tr>
+                        <td>"class"</td>
+                        <td>"MaybeSignal<String>"</td>
+                        <td>"Default::default()"</td>
+                        <td>"Addtional classes for the select element."</td>
+                    </tr>
                 </tbody>
             </Table>
         </div>
diff --git a/demo/src/pages/slider/mod.rs b/demo/src/pages/slider/mod.rs
index 493beb6..91835f9 100644
--- a/demo/src/pages/slider/mod.rs
+++ b/demo/src/pages/slider/mod.rs
@@ -114,6 +114,12 @@ pub fn SliderPage() -> impl IntoView {
                         <td></td>
                         <td>"Slider labels."</td>
                     </tr>
+                    <tr>
+                        <td>"class"</td>
+                        <td>"MaybeSignal<String>"</td>
+                        <td>"Default::default()"</td>
+                        <td>"Addtional classes for the slider element."</td>
+                    </tr>
                 </tbody>
             </Table>
             <h3>"SliderLabel Props"</h3>
diff --git a/demo/src/pages/space/mod.rs b/demo/src/pages/space/mod.rs
index 2db6653..da07c37 100644
--- a/demo/src/pages/space/mod.rs
+++ b/demo/src/pages/space/mod.rs
@@ -112,6 +112,12 @@ pub fn SpacePage() -> impl IntoView {
                         <td></td>
                         <td>"Space's content."</td>
                     </tr>
+                    <tr>
+                        <td>"class"</td>
+                        <td>"MaybeSignal<String>"</td>
+                        <td>"Default::default()"</td>
+                        <td>"Addtional classes for the space element."</td>
+                    </tr>
                 </tbody>
             </Table>
         </div>
diff --git a/demo/src/pages/switch/mod.rs b/demo/src/pages/switch/mod.rs
index 2f5d4c6..6829192 100644
--- a/demo/src/pages/switch/mod.rs
+++ b/demo/src/pages/switch/mod.rs
@@ -42,6 +42,12 @@ pub fn SwitchPage() -> impl IntoView {
                         <td>"false"</td>
                         <td>"Swith's value."</td>
                     </tr>
+                    <tr>
+                        <td>"class"</td>
+                        <td>"MaybeSignal<String>"</td>
+                        <td>"Default::default()"</td>
+                        <td>"Addtional classes for the switch element."</td>
+                    </tr>
                 </tbody>
             </Table>
         </div>
diff --git a/demo/src/pages/table/mod.rs b/demo/src/pages/table/mod.rs
index 79c6e2c..d335184 100644
--- a/demo/src/pages/table/mod.rs
+++ b/demo/src/pages/table/mod.rs
@@ -96,6 +96,12 @@ pub fn TablePage() -> impl IntoView {
                         <td></td>
                         <td>"Table's content."</td>
                     </tr>
+                    <tr>
+                        <td>"class"</td>
+                        <td>"MaybeSignal<String>"</td>
+                        <td>"Default::default()"</td>
+                        <td>"Addtional classes for the table element."</td>
+                    </tr>
                 </tbody>
             </Table>
         </div>
diff --git a/demo/src/pages/tabs/mod.rs b/demo/src/pages/tabs/mod.rs
index 30e33cc..d6a36e5 100644
--- a/demo/src/pages/tabs/mod.rs
+++ b/demo/src/pages/tabs/mod.rs
@@ -69,6 +69,12 @@ pub fn TabsPage() -> impl IntoView {
                         <td></td>
                         <td>"Tabs content."</td>
                     </tr>
+                    <tr>
+                        <td>"class"</td>
+                        <td>"MaybeSignal<String>"</td>
+                        <td>"Default::default()"</td>
+                        <td>"Addtional classes for the tabs element."</td>
+                    </tr>
                 </tbody>
             </Table>
             <h3>"Tab Props"</h3>
@@ -106,6 +112,12 @@ pub fn TabsPage() -> impl IntoView {
                         <td></td>
                         <td>"Tab's content."</td>
                     </tr>
+                    <tr>
+                        <td>"class"</td>
+                        <td>"MaybeSignal<String>"</td>
+                        <td>"Default::default()"</td>
+                        <td>"Addtional classes for the tab element."</td>
+                    </tr>
                 </tbody>
             </Table>
         </div>
diff --git a/demo/src/pages/tag/mod.rs b/demo/src/pages/tag/mod.rs
index 8164ef8..f3b7fb2 100644
--- a/demo/src/pages/tag/mod.rs
+++ b/demo/src/pages/tag/mod.rs
@@ -62,6 +62,12 @@ pub fn TagPage() -> impl IntoView {
                         <td></td>
                         <td>"Tag's content."</td>
                     </tr>
+                    <tr>
+                        <td>"class"</td>
+                        <td>"MaybeSignal<String>"</td>
+                        <td>"Default::default()"</td>
+                        <td>"Addtional classes for the tag element."</td>
+                    </tr>
                 </tbody>
             </Table>
         </div>
diff --git a/demo/src/pages/time_picker/mod.rs b/demo/src/pages/time_picker/mod.rs
index dee2dfa..96a7866 100644
--- a/demo/src/pages/time_picker/mod.rs
+++ b/demo/src/pages/time_picker/mod.rs
@@ -47,6 +47,12 @@ pub fn TimePickerPage() -> impl IntoView {
                         <td></td>
                         <td></td>
                     </tr>
+                    <tr>
+                        <td>"class"</td>
+                        <td>"MaybeSignal<String>"</td>
+                        <td>"Default::default()"</td>
+                        <td>"Addtional classes for the time picker element."</td>
+                    </tr>
                 </tbody>
             </Table>
         </div>
diff --git a/demo/src/pages/typography/mod.rs b/demo/src/pages/typography/mod.rs
index 5b6762b..01f2816 100644
--- a/demo/src/pages/typography/mod.rs
+++ b/demo/src/pages/typography/mod.rs
@@ -60,6 +60,12 @@ pub fn TypographyPage() -> impl IntoView {
                         <td></td>
                         <td>"Text's content."</td>
                     </tr>
+                    <tr>
+                        <td>"class"</td>
+                        <td>"MaybeSignal<String>"</td>
+                        <td>"Default::default()"</td>
+                        <td>"Addtional classes for the text element."</td>
+                    </tr>
                 </tbody>
             </Table>
         </div>
diff --git a/src/badge/badge.css b/src/badge/badge.css
index ba241da..e245bbc 100644
--- a/src/badge/badge.css
+++ b/src/badge/badge.css
@@ -6,6 +6,7 @@
     position: absolute;
     color: var(--thaw-font-color);
     background-color: var(--thaw-background-color);
+    z-index: 10;
 }
 .thaw-badge__sup--value {
     top: -9px;
diff --git a/src/badge/mod.rs b/src/badge/mod.rs
index 3c100cf..1874956 100644
--- a/src/badge/mod.rs
+++ b/src/badge/mod.rs
@@ -1,4 +1,11 @@
-use crate::{theme::use_theme, utils::mount_style, Theme};
+#[cfg(not(feature = "ssr"))]
+use crate::utils::dyn_classes;
+
+use crate::{
+    theme::use_theme,
+    utils::{mount_style, ssr_class},
+    Theme,
+};
 use leptos::*;
 
 #[derive(Default, Clone)]
@@ -25,6 +32,7 @@ pub fn Badge(
     #[prop(default = MaybeSignal::Static(u32::MAX), into)] max: MaybeSignal<u32>,
     #[prop(optional, into)] variant: MaybeSignal<BadgeVariant>,
     #[prop(optional, into)] dot: MaybeSignal<bool>,
+    #[prop(optional, into)] class: MaybeSignal<String>,
     children: Children,
 ) -> impl IntoView {
     let theme = use_theme(Theme::light);
@@ -51,9 +59,12 @@ pub fn Badge(
             value.to_string()
         }
     });
+    let ssr_class = ssr_class(&class);
     view! {
         <div class="thaw-badge" style=move || css_vars.get()>
             <div
+                class=ssr_class
+                use:dyn_classes=class
                 class="thaw-badge__sup"
                 class=("thaw-badge__sup--value", move || !dot.get() && !value.get().is_empty())
                 class=("thaw-badge__sup--dot", move || dot.get())
diff --git a/src/breadcrumb/breadcrumb_item.rs b/src/breadcrumb/breadcrumb_item.rs
index 9926710..d71c1f5 100644
--- a/src/breadcrumb/breadcrumb_item.rs
+++ b/src/breadcrumb/breadcrumb_item.rs
@@ -1,12 +1,22 @@
 use super::use_breadcrumb_separator;
 use leptos::*;
 
+#[cfg(not(feature = "ssr"))]
+use crate::utils::dyn_classes;
+use crate::utils::ssr_class;
+
 #[component]
-pub fn BreadcrumbItem(children: Children) -> impl IntoView {
+pub fn BreadcrumbItem(
+    #[prop(optional, into)] class: MaybeSignal<String>,
+    children: Children,
+) -> impl IntoView {
     let breadcrumb_separator = use_breadcrumb_separator();
+    let ssr_class = ssr_class(&class);
     view! {
         <li class="thaw-breadcrumb-item">
-            <span class="thaw-breadcrumb-item__link">{children()}</span>
+            <span class=ssr_class use:dyn_classes=class class="thaw-breadcrumb-item__link">
+                {children()}
+            </span>
             <span class="thaw-breadcrumb-item__separator">
                 {move || breadcrumb_separator.0.get()}
             </span>
diff --git a/src/breadcrumb/mod.rs b/src/breadcrumb/mod.rs
index b311bee..ef7e5ee 100644
--- a/src/breadcrumb/mod.rs
+++ b/src/breadcrumb/mod.rs
@@ -1,7 +1,12 @@
 mod breadcrumb_item;
 mod theme;
 
-use crate::{use_theme, utils::mount_style, Theme};
+use crate::utils::dyn_classes;
+use crate::{
+    use_theme,
+    utils::{mount_style, ssr_class},
+    Theme,
+};
 pub use breadcrumb_item::BreadcrumbItem;
 use leptos::*;
 pub use theme::BreadcrumbTheme;
@@ -9,6 +14,7 @@ pub use theme::BreadcrumbTheme;
 #[component]
 pub fn Breadcrumb(
     #[prop(default = MaybeSignal::Static("/".to_string()),into)] separator: MaybeSignal<String>,
+    #[prop(optional, into)] class: MaybeSignal<String>,
     children: Children,
 ) -> impl IntoView {
     mount_style("breadcrumb", include_str!("./breadcrumb.css"));
@@ -31,9 +37,15 @@ pub fn Breadcrumb(
         });
         css_vars
     });
+    let ssr_class = ssr_class(&class);
     view! {
         <Provider value=BreadcrumbSeparatorInjection(separator)>
-            <nav class="thaw-breadcrumb" style=move || css_vars.get()>
+            <nav
+                class=ssr_class
+                use:dyn_classes=class
+                class="thaw-breadcrumb"
+                style=move || css_vars.get()
+            >
                 <ul>{children()}</ul>
             </nav>
         </Provider>
diff --git a/src/calendar/mod.rs b/src/calendar/mod.rs
index 7b2f8b0..578ef37 100644
--- a/src/calendar/mod.rs
+++ b/src/calendar/mod.rs
@@ -1,9 +1,11 @@
 mod theme;
 
+#[cfg(not(feature = "ssr"))]
+use crate::utils::dyn_classes;
 use crate::{
     chrono::{Datelike, Days, Local, NaiveDate},
     use_theme,
-    utils::mount_style,
+    utils::{mount_style, ssr_class},
     Button, ButtonGroup, ButtonVariant, Theme,
 };
 use chrono::{Month, Months};
@@ -13,7 +15,10 @@ use std::ops::Deref;
 pub use theme::CalendarTheme;
 
 #[component]
-pub fn Calendar(#[prop(optional, into)] value: RwSignal<Option<NaiveDate>>) -> impl IntoView {
+pub fn Calendar(
+    #[prop(optional, into)] class: MaybeSignal<String>,
+    #[prop(optional, into)] value: RwSignal<Option<NaiveDate>>,
+) -> impl IntoView {
     mount_style("calendar", include_str!("./calendar.css"));
     let theme = use_theme(Theme::light);
     let css_vars = create_memo(move |_| {
@@ -112,8 +117,14 @@ pub fn Calendar(#[prop(optional, into)] value: RwSignal<Option<NaiveDate>>) -> i
             *date = *date + Months::new(1);
         });
     };
+    let ssr_class = ssr_class(&class);
     view! {
-        <div class="thaw-calendar" style=move || css_vars.get()>
+        <div
+            class=ssr_class
+            use:dyn_classes=class
+            class="thaw-calendar"
+            style=move || css_vars.get()
+        >
             <div class="thaw-calendar__header">
                 <span class="thaw-calendar__header-title">
 
diff --git a/src/card/card.css b/src/card/card.css
index cd29be7..c461ef2 100644
--- a/src/card/card.css
+++ b/src/card/card.css
@@ -4,6 +4,7 @@
     border: 1px solid var(--thaw-border-color);
     border-radius: 3px;
     overflow: hidden;
+    background-color: var(--thaw-background-color); /* moving here so that applying padding to card element works correctly */
 }
 .thaw-card__header {
     font-weight: 600;
@@ -21,7 +22,6 @@
 .thaw-card__content,
 .thaw-card__footer {
     padding: 12px 28px;
-    background-color: var(--thaw-background-color);
 }
 .thaw-card__header {
     padding: 20px 28px;
diff --git a/src/card/mod.rs b/src/card/mod.rs
index 8ce1955..c3d2e79 100644
--- a/src/card/mod.rs
+++ b/src/card/mod.rs
@@ -1,4 +1,11 @@
-use crate::{components::*, use_theme, utils::mount_style, Theme};
+#[cfg(not(feature = "ssr"))]
+use crate::utils::dyn_classes;
+use crate::{
+    components::*,
+    use_theme,
+    utils::{mount_style, ssr_class},
+    Theme,
+};
 use leptos::*;
 
 #[derive(Clone)]
@@ -25,6 +32,7 @@ pub fn Card(
     #[prop(optional, into)] title: MaybeSignal<String>,
     #[prop(optional)] card_header: Option<CardHeader>,
     #[prop(optional)] card_header_extra: Option<CardHeaderExtra>,
+    #[prop(optional, into)] class: MaybeSignal<String>,
     children: Children,
     #[prop(optional)] card_footer: Option<CardFooter>,
 ) -> impl IntoView {
@@ -51,8 +59,9 @@ pub fn Card(
     let header = store_value(card_header);
     let header_extra = store_value(card_header_extra);
 
+    let ssr_class = ssr_class(&class);
     view! {
-        <div class="thaw-card" style=move || css_vars.get()>
+        <div class=ssr_class use:dyn_classes=class class="thaw-card" style=move || css_vars.get()>
             <If cond=is_header>
                 <Then slot>
                     <div class="thaw-card__header">
diff --git a/src/checkbox/checkbox_item.rs b/src/checkbox/checkbox_item.rs
index a31e178..cd49a2c 100644
--- a/src/checkbox/checkbox_item.rs
+++ b/src/checkbox/checkbox_item.rs
@@ -7,6 +7,7 @@ use leptos::*;
 #[component]
 pub fn CheckboxItem(
     #[prop(optional, into)] label: Option<String>,
+    #[prop(optional, into)] class: MaybeSignal<String>,
     #[prop(into)] key: String,
 ) -> impl IntoView {
     let checkbox_group = use_checkbox_group();
@@ -32,5 +33,9 @@ pub fn CheckboxItem(
         item_key.get_value()
     };
 
-    view! { <Checkbox value=checked>{label}</Checkbox> }
+    view! {
+        <Checkbox class value=checked>
+            {label}
+        </Checkbox>
+    }
 }
diff --git a/src/checkbox/mod.rs b/src/checkbox/mod.rs
index 17248a8..c27a5ea 100644
--- a/src/checkbox/mod.rs
+++ b/src/checkbox/mod.rs
@@ -1,7 +1,15 @@
 mod checkbox_group;
 mod checkbox_item;
 
-use crate::{components::*, icon::*, theme::use_theme, utils::mount_style, Theme};
+#[cfg(not(feature = "ssr"))]
+use crate::utils::dyn_classes;
+use crate::{
+    components::*,
+    icon::*,
+    theme::use_theme,
+    utils::{mount_style, ssr_class},
+    Theme,
+};
 pub use checkbox_group::CheckboxGroup;
 pub use checkbox_item::CheckboxItem;
 use icondata::AiIcon;
@@ -10,6 +18,7 @@ use leptos::*;
 #[component]
 pub fn Checkbox(
     #[prop(optional, into)] value: RwSignal<bool>,
+    #[prop(optional, into)] class: MaybeSignal<String>,
     children: Children,
 ) -> impl IntoView {
     let theme = use_theme(Theme::light);
@@ -26,8 +35,11 @@ pub fn Checkbox(
         css_vars
     });
 
+    let ssr_class = ssr_class(&class);
     view! {
         <div
+            class=ssr_class
+            use:dyn_classes=class
             class:thaw-checkbox=true
             class=("thaw-checkbox--checked", move || value.get())
             style=move || css_vars.get()
diff --git a/src/color_picker/mod.rs b/src/color_picker/mod.rs
index 4c99756..18d1c7b 100644
--- a/src/color_picker/mod.rs
+++ b/src/color_picker/mod.rs
@@ -2,14 +2,22 @@ mod color;
 mod theme;
 
 use crate::components::{Binder, Follower, FollowerPlacement};
-use crate::{use_theme, utils::mount_style, Theme};
+use crate::utils::dyn_classes;
+use crate::{
+    use_theme,
+    utils::{mount_style, ssr_class},
+    Theme,
+};
 pub use color::*;
 use leptos::leptos_dom::helpers::WindowListenerHandle;
 use leptos::*;
 pub use theme::ColorPickerTheme;
 
 #[component]
-pub fn ColorPicker(#[prop(optional, into)] value: RwSignal<RGBA>) -> impl IntoView {
+pub fn ColorPicker(
+    #[prop(optional, into)] value: RwSignal<RGBA>,
+    #[prop(optional, into)] class: MaybeSignal<String>,
+) -> impl IntoView {
     mount_style("color-picker", include_str!("./color-picker.css"));
     let theme = use_theme(Theme::light);
     let popover_css_vars = create_memo(move |_| {
@@ -90,9 +98,16 @@ pub fn ColorPicker(#[prop(optional, into)] value: RwSignal<RGBA>) -> impl IntoVi
         on_cleanup(move || timer.remove());
     }
 
+    let ssr_class = ssr_class(&class);
     view! {
         <Binder target_ref=trigger_ref>
-            <div class="thaw-color-picker-trigger" on:click=show_popover ref=trigger_ref>
+            <div
+                class=ssr_class
+                use:dyn_classes=class
+                class="thaw-color-picker-trigger"
+                on:click=show_popover
+                ref=trigger_ref
+            >
                 <div class="thaw-color-picker-trigger__content" style=move || style.get()>
                     {move || label.get()}
                 </div>
diff --git a/src/divider/mod.rs b/src/divider/mod.rs
index b021766..a66ba6c 100644
--- a/src/divider/mod.rs
+++ b/src/divider/mod.rs
@@ -1,12 +1,15 @@
 use leptos::*;
 
-use crate::utils::mount_style;
+#[cfg(not(feature = "ssr"))]
+use crate::utils::dyn_classes;
+use crate::utils::{mount_style, ssr_class};
 
 #[component]
-pub fn Divider() -> impl IntoView {
+pub fn Divider(#[prop(optional, into)] class: MaybeSignal<String>) -> impl IntoView {
     mount_style("divider", include_str!("./divider.css"));
+    let ssr_class = ssr_class(&class);
     view! {
-        <div class="thaw-divider">
+        <div class=ssr_class use:dyn_classes=class class="thaw-divider">
             <div class="thaw-divider__line"></div>
         </div>
     }
diff --git a/src/grid/grid_item.rs b/src/grid/grid_item.rs
index 232a923..70d7737 100644
--- a/src/grid/grid_item.rs
+++ b/src/grid/grid_item.rs
@@ -1,10 +1,15 @@
 use super::use_grid;
 use leptos::*;
 
+#[cfg(not(feature = "ssr"))]
+use crate::utils::dyn_classes;
+use crate::utils::ssr_class;
+
 #[component]
 pub fn GridItem(
     #[prop(default = MaybeSignal::Static(1u16), into)] column: MaybeSignal<u16>,
     #[prop(optional, into)] offset: MaybeSignal<u16>,
+    #[prop(optional, into)] class: MaybeSignal<String>,
     children: Children,
 ) -> impl IntoView {
     let grid = use_grid();
@@ -32,8 +37,9 @@ pub fn GridItem(
 
         style
     });
+    let ssr_class = ssr_class(&class);
     view! {
-        <div class="thaw-grid-item" style=move || style.get()>
+        <div class=ssr_class use:dyn_classes=class class="thaw-grid-item" style=move || style.get()>
             {children()}
         </div>
     }
diff --git a/src/grid/mod.rs b/src/grid/mod.rs
index f1278f3..19a1231 100644
--- a/src/grid/mod.rs
+++ b/src/grid/mod.rs
@@ -1,5 +1,8 @@
 mod grid_item;
 
+use crate::utils::dyn_classes;
+use crate::utils::ssr_class;
+
 pub use grid_item::*;
 use leptos::*;
 
@@ -8,6 +11,7 @@ pub fn Grid(
     #[prop(default = MaybeSignal::Static(1u16), into)] cols: MaybeSignal<u16>,
     #[prop(optional, into)] x_gap: MaybeSignal<u16>,
     #[prop(optional, into)] y_gap: MaybeSignal<u16>,
+    #[prop(optional, into)] class: MaybeSignal<String>,
     children: Children,
 ) -> impl IntoView {
     let style = create_memo(move |_| {
@@ -20,9 +24,10 @@ pub fn Grid(
         style
     });
 
+    let ssr_class = ssr_class(&class);
     view! {
         <Provider value=GridInjection::new(x_gap)>
-            <div class="thaw-grid" style=move || style.get()>
+            <div class=ssr_class use:dyn_classes=class class="thaw-grid" style=move || style.get()>
                 {children()}
             </div>
         </Provider>
diff --git a/src/image/mod.rs b/src/image/mod.rs
index 9b362be..3d9aa4f 100644
--- a/src/image/mod.rs
+++ b/src/image/mod.rs
@@ -1,5 +1,9 @@
 use leptos::*;
 
+#[cfg(not(feature = "ssr"))]
+use crate::utils::dyn_classes;
+use crate::utils::ssr_class;
+
 #[component]
 pub fn Image(
     #[prop(optional, into)] src: MaybeSignal<String>,
@@ -8,6 +12,7 @@ pub fn Image(
     #[prop(optional, into)] height: MaybeSignal<String>,
     #[prop(optional, into)] border_radius: MaybeSignal<String>,
     #[prop(optional, into)] object_fit: MaybeSignal<String>,
+    #[prop(optional, into)] class: MaybeSignal<String>,
 ) -> impl IntoView {
     let style = move || {
         let mut style = String::new();
@@ -29,8 +34,12 @@ pub fn Image(
 
         style
     };
+
+    let ssr_class = ssr_class(&class);
     view! {
         <img
+            class=ssr_class
+            use:dyn_classes=class
             src=move || src.get()
             alt=move || alt.get()
             style=style
diff --git a/src/input/mod.rs b/src/input/mod.rs
index 2d37cdf..6feabbc 100644
--- a/src/input/mod.rs
+++ b/src/input/mod.rs
@@ -1,8 +1,10 @@
 mod theme;
 
+#[cfg(not(feature = "ssr"))]
+use crate::utils::dyn_classes;
 use crate::{
     theme::{use_theme, Theme},
-    utils::{mount_style, ComponentRef},
+    utils::{mount_style, ssr_class, ComponentRef},
 };
 use leptos::*;
 pub use theme::InputTheme;
@@ -50,6 +52,7 @@ pub fn Input(
     #[prop(optional)] input_prefix: Option<InputPrefix>,
     #[prop(optional)] input_suffix: Option<InputSuffix>,
     #[prop(optional)] comp_ref: ComponentRef<InputRef>,
+    #[prop(optional, into)] class: MaybeSignal<String>,
 ) -> impl IntoView {
     let theme = use_theme(Theme::light);
     mount_style("input", include_str!("./input.css"));
@@ -123,8 +126,12 @@ pub fn Input(
     input_ref.on_load(move |_| {
         comp_ref.load(InputRef { input_ref });
     });
+
+    let ssr_class = ssr_class(&class);
     view! {
         <div
+            class=ssr_class
+            use:dyn_classes=class
             class="thaw-input"
             class=("thaw-input--focus", move || is_focus.get())
             class=("thaw-input--disabled", move || disabled.get())
diff --git a/src/input_number/mod.rs b/src/input_number/mod.rs
index 0c32d61..b7c0920 100644
--- a/src/input_number/mod.rs
+++ b/src/input_number/mod.rs
@@ -11,6 +11,7 @@ pub fn InputNumber<T>(
     #[prop(into)] step: MaybeSignal<T>,
     #[prop(optional, into)] disabled: MaybeSignal<bool>,
     #[prop(optional, into)] invalid: MaybeSignal<bool>,
+    #[prop(optional, into)] class: MaybeSignal<String>,
 ) -> impl IntoView
 where
     T: Add<Output = T> + Sub<Output = T>,
@@ -46,7 +47,7 @@ where
         value.set(value.get_untracked() - step.get_untracked());
     });
     view! {
-        <Input value=input_value allow_value placeholder disabled invalid>
+        <Input class value=input_value allow_value placeholder disabled invalid>
             <InputSuffix slot>
                 <Button disabled variant=ButtonVariant::Link on_click=sub>
                     <Icon icon=Icon::from(AiIcon::AiMinusOutlined) style="font-size: 18px"/>
diff --git a/src/menu/menu_group.rs b/src/menu/menu_group.rs
index d4a5260..017e182 100644
--- a/src/menu/menu_group.rs
+++ b/src/menu/menu_group.rs
@@ -1,8 +1,18 @@
-use crate::{theme::use_theme, utils::mount_style, Theme};
+#[cfg(not(feature = "ssr"))]
+use crate::utils::dyn_classes;
+use crate::{
+    theme::use_theme,
+    utils::{mount_style, ssr_class},
+    Theme,
+};
 use leptos::*;
 
 #[component]
-pub fn MenuGroup(#[prop(into)] label: String, children: Children) -> impl IntoView {
+pub fn MenuGroup(
+    #[prop(into)] label: String,
+    #[prop(optional, into)] class: MaybeSignal<String>,
+    children: Children,
+) -> impl IntoView {
     mount_style("menu-group", include_str!("./menu-group.css"));
     let theme = use_theme(Theme::light);
     let css_vars = create_memo(move |_| {
@@ -12,8 +22,14 @@ pub fn MenuGroup(#[prop(into)] label: String, children: Children) -> impl IntoVi
         });
         css_vars
     });
+    let ssr_class = ssr_class(&class);
     view! {
-        <div class="thaw-menu-group" style=move || css_vars.get()>
+        <div
+            class=ssr_class
+            use:dyn_classes=class
+            class="thaw-menu-group"
+            style=move || css_vars.get()
+        >
             {label}
         </div>
         {children()}
diff --git a/src/menu/menu_item.rs b/src/menu/menu_item.rs
index e4fce27..9774963 100644
--- a/src/menu/menu_item.rs
+++ b/src/menu/menu_item.rs
@@ -1,11 +1,19 @@
 use super::use_menu;
-use crate::{theme::use_theme, utils::mount_style, Theme};
+
+#[cfg(not(feature = "ssr"))]
+use crate::utils::dyn_classes;
+use crate::{
+    theme::use_theme,
+    utils::{mount_style, ssr_class},
+    Theme,
+};
 use leptos::*;
 
 #[component]
 pub fn MenuItem(
     #[prop(into)] key: MaybeSignal<String>,
     #[prop(into)] label: MaybeSignal<String>,
+    #[prop(optional, into)] class: MaybeSignal<String>,
 ) -> impl IntoView {
     mount_style("menu-item", include_str!("./menu-item.css"));
     let theme = use_theme(Theme::light);
@@ -32,9 +40,12 @@ pub fn MenuItem(
         });
         css_vars
     });
+    let ssr_class = ssr_class(&class);
     view! {
         <div class="thaw-menu-item">
             <div
+                class=ssr_class
+                use:dyn_classes=class
                 class="thaw-menu-item__content"
                 class=("thaw-menu-item__content--selected", move || menu.0.get() == key.get())
                 on:click=on_click
diff --git a/src/menu/mod.rs b/src/menu/mod.rs
index 3e291d2..d8b09cf 100644
--- a/src/menu/mod.rs
+++ b/src/menu/mod.rs
@@ -2,16 +2,26 @@ mod menu_group;
 mod menu_item;
 mod theme;
 
+use crate::utils::dyn_classes;
+use crate::utils::ssr_class;
+
 use leptos::*;
 pub use menu_group::MenuGroup;
 pub use menu_item::*;
 pub use theme::MenuTheme;
 
 #[component]
-pub fn Menu(#[prop(optional, into)] value: RwSignal<String>, children: Children) -> impl IntoView {
+pub fn Menu(
+    #[prop(optional, into)] value: RwSignal<String>,
+    #[prop(optional, into)] class: MaybeSignal<String>,
+    children: Children,
+) -> impl IntoView {
+    let ssr_class = ssr_class(&class);
     view! {
         <Provider value=MenuInjection(value)>
-            <div class="thaw-menu">{children()}</div>
+            <div class=ssr_class use:dyn_classes=class class="thaw-menu">
+                {children()}
+            </div>
         </Provider>
     }
 }
diff --git a/src/mobile/nav_bar/mod.rs b/src/mobile/nav_bar/mod.rs
index 3975587..ba589ee 100644
--- a/src/mobile/nav_bar/mod.rs
+++ b/src/mobile/nav_bar/mod.rs
@@ -1,10 +1,12 @@
 mod theme;
 
+#[cfg(not(feature = "ssr"))]
+use crate::utils::dyn_classes;
 use crate::{
     components::*,
     icon::*,
     use_theme,
-    utils::{mount_style, StoredMaybeSignal},
+    utils::{mount_style, ssr_class, StoredMaybeSignal},
     Theme,
 };
 use leptos::*;
@@ -18,6 +20,7 @@ pub fn NavBar(
     #[prop(optional, into)] on_click_left: Option<Callback<ev::MouseEvent>>,
     #[prop(optional, into)] right_text: MaybeSignal<String>,
     #[prop(optional, into)] on_click_right: Option<Callback<ev::MouseEvent>>,
+    #[prop(optional, into)] class: MaybeSignal<String>,
 ) -> impl IntoView {
     mount_style("nav-bar", include_str!("./nav-bar.css"));
     let theme = use_theme(Theme::light);
@@ -45,8 +48,14 @@ pub fn NavBar(
         }
     };
 
+    let ssr_class = ssr_class(&class);
     view! {
-        <div class="thaw-nav-bar" style=move || css_vars.get()>
+        <div
+            class=ssr_class
+            use:dyn_classes=class
+            class="thaw-nav-bar"
+            style=move || css_vars.get()
+        >
             <If cond=MaybeSignal::derive(move || left_arrow.get() || !left_text.get().is_empty())>
                 <Then slot>
                     <div class="thaw-nav-bar__left" on:click=on_click_left>
diff --git a/src/radio/mod.rs b/src/radio/mod.rs
index 99fd1cf..c7fc6ce 100644
--- a/src/radio/mod.rs
+++ b/src/radio/mod.rs
@@ -1,8 +1,18 @@
-use crate::{theme::use_theme, utils::mount_style, Theme};
+#[cfg(not(feature = "ssr"))]
+use crate::utils::dyn_classes;
+use crate::{
+    theme::use_theme,
+    utils::{mount_style, ssr_class},
+    Theme,
+};
 use leptos::*;
 
 #[component]
-pub fn Radio(#[prop(optional, into)] value: RwSignal<bool>, children: Children) -> impl IntoView {
+pub fn Radio(
+    #[prop(optional, into)] value: RwSignal<bool>,
+    #[prop(optional, into)] class: MaybeSignal<String>,
+    children: Children,
+) -> impl IntoView {
     let theme = use_theme(Theme::light);
     mount_style("radio", include_str!("./radio.css"));
 
@@ -16,8 +26,11 @@ pub fn Radio(#[prop(optional, into)] value: RwSignal<bool>, children: Children)
         css_vars
     });
 
+    let ssr_class = ssr_class(&class);
     view! {
         <div
+            class=ssr_class
+            use:dyn_classes=class
             class="thaw-radio"
             class=("thaw-radio--checked", move || value.get())
             style=move || css_vars.get()
diff --git a/src/select/mod.rs b/src/select/mod.rs
index 011fe62..7416693 100644
--- a/src/select/mod.rs
+++ b/src/select/mod.rs
@@ -1,9 +1,10 @@
 mod theme;
 
+use crate::utils::dyn_classes;
 use crate::{
     components::{Binder, Follower, FollowerPlacement, FollowerWidth},
     theme::use_theme,
-    utils::mount_style,
+    utils::{mount_style, ssr_class},
     Theme,
 };
 use leptos::*;
@@ -20,6 +21,7 @@ pub struct SelectOption<T> {
 pub fn Select<T>(
     #[prop(optional, into)] value: RwSignal<Option<T>>,
     #[prop(optional, into)] options: MaybeSignal<Vec<SelectOption<T>>>,
+    #[prop(optional, into)] class: MaybeSignal<String>,
 ) -> impl IntoView
 where
     T: Eq + Hash + Clone + 'static,
@@ -106,9 +108,12 @@ where
             .map_or(String::new(), |v| v.label.clone()),
         None => String::new(),
     });
+    let ssr_class = ssr_class(&class);
     view! {
         <Binder target_ref=trigger_ref>
             <div
+                class=ssr_class
+                use:dyn_classes=class
                 class="thaw-select"
                 ref=trigger_ref
                 on:click=show_menu
diff --git a/src/slider/mod.rs b/src/slider/mod.rs
index 17f8ba3..6ad6c73 100644
--- a/src/slider/mod.rs
+++ b/src/slider/mod.rs
@@ -1,7 +1,14 @@
 mod slider_label;
 mod theme;
 
-use crate::{components::OptionComp, theme::use_theme, utils::mount_style, Theme};
+#[cfg(not(feature = "ssr"))]
+use crate::utils::dyn_classes;
+use crate::{
+    components::OptionComp,
+    theme::use_theme,
+    utils::{mount_style, ssr_class},
+    Theme,
+};
 use leptos::*;
 use web_sys::DomRect;
 
@@ -13,6 +20,7 @@ pub fn Slider(
     #[prop(optional, into)] value: RwSignal<f64>,
     #[prop(default = MaybeSignal::Static(100f64), into)] max: MaybeSignal<f64>,
     #[prop(optional, into)] step: MaybeSignal<f64>,
+    #[prop(optional, into)] class: MaybeSignal<String>,
     #[prop(optional)] children: Option<Children>,
 ) -> impl IntoView {
     mount_style("slider", include_str!("./slider.css"));
@@ -110,8 +118,15 @@ pub fn Slider(
     });
     on_cleanup(move || on_mouse_move.remove());
 
+    let ssr_class = ssr_class(&class);
     view! {
-        <div class="thaw-slider" style=move || css_vars.get() on:click=on_mouse_click>
+        <div
+            class=ssr_class
+            use:dyn_classes=class
+            class="thaw-slider"
+            style=move || css_vars.get()
+            on:click=on_mouse_click
+        >
             <div class="thaw-slider-rail" ref=rail_ref>
                 <div
                     class="thaw-slider-rail__fill"
@@ -126,6 +141,7 @@ pub fn Slider(
                 class="thaw-slider-handle"
                 style=move || { format!("left: {}%", percentage.get()) }
             ></div>
+
         </div>
     }
 }
diff --git a/src/space/mod.rs b/src/space/mod.rs
index 33857e9..1c3a2d5 100644
--- a/src/space/mod.rs
+++ b/src/space/mod.rs
@@ -1,4 +1,6 @@
-use crate::utils::mount_style;
+#[cfg(not(feature = "ssr"))]
+use crate::utils::dyn_classes;
+use crate::utils::{mount_style, ssr_class};
 use leptos::*;
 
 #[derive(Default)]
@@ -16,6 +18,7 @@ pub enum SpaceGap {
 pub fn Space(
     #[prop(optional)] gap: SpaceGap,
     #[prop(optional)] vertical: bool,
+    #[prop(optional, into)] class: MaybeSignal<String>,
     children: Children,
 ) -> impl IntoView {
     mount_style("space", include_str!("./space.css"));
@@ -27,8 +30,11 @@ pub fn Space(
         SpaceGap::WH(width, height) => format!("{width}px {height}px"),
     };
 
+    let ssr_class = ssr_class(&class);
     view! {
         <div
+            class=ssr_class
+            use:dyn_classes=class
             class="thaw-space"
             style:gap=gap
             style:flex-direction=if vertical { "column" } else { "row" }
diff --git a/src/switch/mod.rs b/src/switch/mod.rs
index 1f6aaac..52e26f8 100644
--- a/src/switch/mod.rs
+++ b/src/switch/mod.rs
@@ -1,11 +1,20 @@
 mod theme;
 
-use crate::{theme::use_theme, utils::mount_style, Theme};
+#[cfg(not(feature = "ssr"))]
+use crate::utils::dyn_classes;
+use crate::{
+    theme::use_theme,
+    utils::{mount_style, ssr_class},
+    Theme,
+};
 use leptos::*;
 pub use theme::SwitchTheme;
 
 #[component]
-pub fn Switch(#[prop(optional, into)] value: RwSignal<bool>) -> impl IntoView {
+pub fn Switch(
+    #[prop(optional, into)] value: RwSignal<bool>,
+    #[prop(optional, into)] class: MaybeSignal<String>,
+) -> impl IntoView {
     mount_style("switch", include_str!("./switch.css"));
     let theme = use_theme(Theme::light);
     let css_vars = create_memo(move |_| {
@@ -22,8 +31,11 @@ pub fn Switch(#[prop(optional, into)] value: RwSignal<bool>) -> impl IntoView {
         });
         css_vars
     });
+    let ssr_class = ssr_class(&class);
     view! {
         <div
+            class=ssr_class
+            use:dyn_classes=class
             class="thaw-switch"
             class=("thaw-switch--active", move || value.get())
             style=move || css_vars.get()
diff --git a/src/table/mod.rs b/src/table/mod.rs
index f18bd43..07367ce 100644
--- a/src/table/mod.rs
+++ b/src/table/mod.rs
@@ -1,6 +1,12 @@
 mod theme;
 
-use crate::{theme::use_theme, utils::mount_style, Theme};
+#[cfg(not(feature = "ssr"))]
+use crate::utils::dyn_classes;
+use crate::{
+    theme::use_theme,
+    utils::{mount_style, ssr_class},
+    Theme,
+};
 use leptos::*;
 pub use theme::TableTheme;
 
@@ -8,6 +14,7 @@ pub use theme::TableTheme;
 pub fn Table(
     #[prop(optional, into)] style: MaybeSignal<String>,
     #[prop(default=true.into(), into)] single_row: MaybeSignal<bool>,
+    #[prop(optional, into)] class: MaybeSignal<String>,
     #[prop(optional, into)] single_column: MaybeSignal<bool>,
     children: Children,
 ) -> impl IntoView {
@@ -36,8 +43,11 @@ pub fn Table(
 
         css_vars
     });
+    let ssr_class = ssr_class(&class);
     view! {
         <table
+            class=ssr_class
+            use:dyn_classes=class
             class="thaw-table"
             class=("thaw-table--single-row", move || single_row.get())
             class=("thaw-table--single-column", move || single_column.get())
diff --git a/src/tabs/mod.rs b/src/tabs/mod.rs
index 71ba144..f9fbd81 100644
--- a/src/tabs/mod.rs
+++ b/src/tabs/mod.rs
@@ -1,12 +1,22 @@
 mod tab;
 
-use crate::{theme::use_theme, utils::mount_style, Theme};
+#[cfg(not(feature = "ssr"))]
+use crate::utils::dyn_classes;
+use crate::{
+    theme::use_theme,
+    utils::{mount_style, ssr_class},
+    Theme,
+};
 use leptos::*;
 
 pub use tab::*;
 
 #[component]
-pub fn Tabs(#[prop(optional, into)] value: RwSignal<String>, children: Children) -> impl IntoView {
+pub fn Tabs(
+    #[prop(optional, into)] value: RwSignal<String>,
+    #[prop(optional, into)] class: MaybeSignal<String>,
+    children: Children,
+) -> impl IntoView {
     mount_style("tabs", include_str!("./tabs.css"));
     let tab_options_vec = create_rw_signal(vec![]);
 
@@ -15,7 +25,7 @@ pub fn Tabs(#[prop(optional, into)] value: RwSignal<String>, children: Children)
             active_key: value,
             tab_options_vec,
         }>
-            <TabsInner value tab_options_vec children/>
+            <TabsInner class value tab_options_vec children/>
         </Provider>
     }
 }
@@ -24,6 +34,7 @@ pub fn Tabs(#[prop(optional, into)] value: RwSignal<String>, children: Children)
 fn TabsInner(
     value: RwSignal<String>,
     tab_options_vec: RwSignal<Vec<TabOption>>,
+    #[prop(optional, into)] class: MaybeSignal<String>,
     children: Children,
 ) -> impl IntoView {
     mount_style("tabs", include_str!("./tabs.css"));
@@ -50,8 +61,9 @@ fn TabsInner(
     let label_list_ref = create_node_ref::<html::Div>();
 
     let children = children();
+    let ssr_class = ssr_class(&class);
     view! {
-        <div class="thaw-tabs" style=move || css_vars.get()>
+        <div class=ssr_class use:dyn_classes=class class="thaw-tabs" style=move || css_vars.get()>
             <div class="thaw-tabs__label-list" ref=label_list_ref>
                 <For
                     each=move || tab_options_vec.get()
diff --git a/src/tabs/tab.rs b/src/tabs/tab.rs
index d2fbe27..760ee5f 100644
--- a/src/tabs/tab.rs
+++ b/src/tabs/tab.rs
@@ -1,5 +1,7 @@
 use super::use_tabs;
-use crate::utils::mount_style;
+#[cfg(not(feature = "ssr"))]
+use crate::utils::dyn_classes;
+use crate::utils::{mount_style, ssr_class};
 use leptos::*;
 
 #[derive(Clone)]
@@ -12,6 +14,7 @@ pub(crate) struct TabOption {
 pub fn Tab(
     #[prop(into)] key: String,
     #[prop(into)] label: String,
+    #[prop(optional, into)] class: MaybeSignal<String>,
     children: Children,
 ) -> impl IntoView {
     mount_style("tab", include_str!("./tab.css"));
@@ -20,8 +23,14 @@ pub fn Tab(
         key: key.clone(),
         label,
     });
+    let ssr_class = ssr_class(&class);
     view! {
-        <div class="thaw-tab" class=("thaw-tab--hidden", move || key != tabs.get_key())>
+        <div
+            class=ssr_class
+            use:dyn_classes=class
+            class="thaw-tab"
+            class=("thaw-tab--hidden", move || key != tabs.get_key())
+        >
             {children()}
         </div>
     }
diff --git a/src/tag/mod.rs b/src/tag/mod.rs
index 38a3ce5..5e3c448 100644
--- a/src/tag/mod.rs
+++ b/src/tag/mod.rs
@@ -1,6 +1,12 @@
 mod theme;
 
-use crate::{theme::use_theme, utils::mount_style, Theme};
+#[cfg(not(feature = "ssr"))]
+use crate::utils::dyn_classes;
+use crate::{
+    theme::use_theme,
+    utils::{mount_style, ssr_class},
+    Theme,
+};
 use leptos::*;
 pub use theme::TagTheme;
 
@@ -43,6 +49,7 @@ impl TagVariant {
 #[component]
 pub fn Tag(
     #[prop(optional, into)] variant: MaybeSignal<TagVariant>,
+    #[prop(optional, into)] class: MaybeSignal<String>,
     children: Children,
 ) -> impl IntoView {
     mount_style("tag", include_str!("./tag.css"));
@@ -66,8 +73,9 @@ pub fn Tag(
         });
         css_vars
     });
+    let ssr_class = ssr_class(&class);
     view! {
-        <div class="thaw-tag" style=move || css_vars.get()>
+        <div class=ssr_class use:dyn_classes=class class="thaw-tag" style=move || css_vars.get()>
             <span class="thaw-tag__content">{children()}</span>
         </div>
     }
diff --git a/src/time_picker/mod.rs b/src/time_picker/mod.rs
index 5468560..1dcc6d1 100644
--- a/src/time_picker/mod.rs
+++ b/src/time_picker/mod.rs
@@ -11,7 +11,10 @@ use leptos::*;
 pub use theme::TimePickerTheme;
 
 #[component]
-pub fn TimePicker(#[prop(optional, into)] value: RwSignal<Option<NaiveTime>>) -> impl IntoView {
+pub fn TimePicker(
+    #[prop(optional, into)] value: RwSignal<Option<NaiveTime>>,
+    #[prop(optional, into)] class: MaybeSignal<String>,
+) -> impl IntoView {
     mount_style("time-picker", include_str!("./time-picker.css"));
     let time_picker_ref = create_node_ref::<html::Div>();
     let panel_ref = ComponentRef::<PanelRef>::default();
@@ -70,7 +73,7 @@ pub fn TimePicker(#[prop(optional, into)] value: RwSignal<Option<NaiveTime>>) ->
     view! {
         <Binder target_ref=time_picker_ref>
             <div ref=time_picker_ref>
-                <Input value=show_time_text on_focus=open_panel on_blur=on_input_blur>
+                <Input class value=show_time_text on_focus=open_panel on_blur=on_input_blur>
                     <InputSuffix slot>
                         <Icon
                             icon=Icon::from(AiIcon::AiClockCircleOutlined)
diff --git a/src/typography/text.rs b/src/typography/text.rs
index bc49d0e..160caa6 100644
--- a/src/typography/text.rs
+++ b/src/typography/text.rs
@@ -1,8 +1,18 @@
-use crate::{use_theme, utils::mount_style, Theme};
+#[cfg(not(feature = "ssr"))]
+use crate::utils::dyn_classes;
+use crate::{
+    use_theme,
+    utils::{mount_style, ssr_class},
+    Theme,
+};
 use leptos::*;
 
 #[component]
-pub fn Text(#[prop(optional)] code: bool, children: Children) -> impl IntoView {
+pub fn Text(
+    #[prop(optional)] code: bool,
+    #[prop(optional, into)] class: MaybeSignal<String>,
+    children: Children,
+) -> impl IntoView {
     mount_style("text", include_str!("./text.css"));
     let theme = use_theme(Theme::light);
     let css_vars = create_memo(move |_| {
@@ -16,14 +26,25 @@ pub fn Text(#[prop(optional)] code: bool, children: Children) -> impl IntoView {
         css_vars
     });
 
+    let ssr_class = ssr_class(&class);
     if code {
         view! {
-            <code class="thaw-text thaw-text--code" style=move || css_vars.get()>
+            <code
+                class=ssr_class
+                use:dyn_classes=class
+                class="thaw-text thaw-text--code"
+                style=move || css_vars.get()
+            >
                 {children()}
             </code>
         }
         .into_any()
     } else {
-        view! { <span class="thaw-text">{children()}</span> }.into_any()
+        view! {
+            <span class=ssr_class use:dyn_classes=class class="thaw-text">
+                {children()}
+            </span>
+        }
+        .into_any()
     }
 }