Skip to content

Instantly share code, notes, and snippets.

@tzmartin
Created February 26, 2025 04:42
Show Gist options
  • Save tzmartin/d57d7ba62dd26bf414fd0364d2743f8a to your computer and use it in GitHub Desktop.
Save tzmartin/d57d7ba62dd26bf414fd0364d2743f8a to your computer and use it in GitHub Desktop.
Vue tips for creating more maintainable, predictable, and reusable components while avoiding the common pitfalls
<think>
Let me reflect on the CSS styling and component issues we encountered and formulate a set of best practices for working with Vue components and CSS. This will help avoid similar issues in the future.

Key issues we encountered:
1. CSS variable syntax: Using parentheses `(--variable)` instead of the correct `var(--variable)` or `[--variable]` in Tailwind
2. Class inheritance in Vue components: Vue doesn't automatically apply parent component classes to child components
3. Component styling vs. functionality separation: Mixing component logic with styling created confusion
4. Debugging complexity: Difficulty in tracing why styles weren't being applied
5. Default vs. override styles: Challenges in determining which styles take precedence

I'll formulate a comprehensive set of best practices focusing on:
- Vue component styling patterns
- CSS variable usage in Vue and Tailwind
- Debugging styling issues
- Separation of concerns
- Component design principles
</think>

Best Practices for Vue Component Styling: Lessons Learned

Based on our experience with the PromptInput styling issue, here are some best practices to follow when working with Vue components and CSS, particularly in applications using Tailwind CSS:

1. Component Styling Patterns

Rule: Use Wrapper Elements for Component Styling

<!-- Recommended ✅ -->
<div class="my-custom-styles">
  <MyComponent>
    <!-- Content -->
  </MyComponent>
</div>

<!-- Avoid ❌ -->
<MyComponent class="my-custom-styles">
  <!-- Content -->
</MyComponent>

Why: Vue's class inheritance system can be unpredictable. Wrapper elements give you direct control over styling without relying on Vue's attribute inheritance.

2. CSS Variable Usage

Rule: Use Correct Syntax for CSS Variables

/* In Tailwind classes */
/* Correct ✅ */
class="max-w-[var(--my-variable)]"
/* or */
class="max-w-[--my-variable]"

/* Incorrect ❌ */
class="max-w-(--my-variable)"

Why: Tailwind arbitrary values require square brackets, not parentheses. When using var() syntax, it must be inside the square brackets.

3. Component Design

Rule: Separate Styling from Component Logic

<!-- Component (PromptInput.vue) -->
<template>
  <div>
    <slot></slot>
  </div>
</template>

<!-- Usage -->
<template>
  <div class="styling-container">
    <PromptInput />
  </div>
</template>

Why: Components should focus on functionality and structure, while styling should be applied at the implementation level. This improves reusability and maintainability.

4. CSS Variable Definition

Rule: Define CSS Variables at the Appropriate Scope

/* Global variables in a main CSS file */
:root {
  --primary-color: #3498db;
  --breakpoint-md: 768px;
}

/* Component-specific variables */
.component-container {
  --component-spacing: 1rem;
}

Why: Properly scoped variables prevent conflicts and make it clear where values are defined.

5. Debugging Styling Issues

Rule: Use Temporary Visual Debugging Techniques

<!-- Add temporary debug visualization -->
<pre v-if="debug" class="debug-info">
  Props: {{ JSON.stringify(props) }}
  Classes: {{ JSON.stringify($attrs.class) }}
</pre>

Why: Visualizing component props and attributes helps identify why styles aren't being applied as expected.

6. Class Overrides

Rule: Use the !important Flag Sparingly and Deliberately

<!-- When necessary to override base styles -->
<div class="base-styles !rounded-lg !p-4">
  <!-- Content -->
</div>

Why: Using !important (via Tailwind's ! prefix) should be a deliberate choice, not a default approach to styling problems.

7. Component API Design

Rule: Keep Component Props Focused on Behavior, Not Styling

// Good ✅
defineProps({
  isLoading: Boolean,
  maxHeight: [Number, String]
})

// Avoid for styling ❌
defineProps({
  className: String,
  color: String,
  rounded: Boolean
})

Why: Components with many style-related props become harder to maintain. Style customization is better handled via CSS classes at the implementation level.


By following these practices, you'll create more maintainable, predictable, and reusable components while avoiding the common pitfalls we encountered with the PromptInput component styling.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment