diff --git a/.changeset/two-hats-ask.md b/.changeset/two-hats-ask.md
new file mode 100644
index 000000000..8d0295c45
--- /dev/null
+++ b/.changeset/two-hats-ask.md
@@ -0,0 +1,5 @@
+---
+'eslint-plugin-svelte': minor
+---
+
+feat(consistent-selector-style): added support for dynamic classes and IDs
diff --git a/packages/eslint-plugin-svelte/src/rules/consistent-selector-style.ts b/packages/eslint-plugin-svelte/src/rules/consistent-selector-style.ts
index 5af44ce1a..8c2b75d33 100644
--- a/packages/eslint-plugin-svelte/src/rules/consistent-selector-style.ts
+++ b/packages/eslint-plugin-svelte/src/rules/consistent-selector-style.ts
@@ -6,10 +6,22 @@ import type {
 	Node as SelectorNode,
 	Tag as SelectorTag
 } from 'postcss-selector-parser';
+import type { SvelteHTMLElement } from 'svelte-eslint-parser/lib/ast';
 import { findClassesInAttribute } from '../utils/ast-utils.js';
 import { getSourceCode } from '../utils/compat.js';
+import {
+	extractExpressionPrefixLiteral,
+	extractExpressionSuffixLiteral
+} from '../utils/expression-affixes.js';
 import { createRule } from '../utils/index.js';
 
+interface Selections {
+	exact: Map<string, AST.SvelteHTMLElement[]>;
+	// [prefix, suffix]
+	affixes: Map<[string | null, string | null], AST.SvelteHTMLElement[]>;
+	universalSelector: boolean;
+}
+
 export default createRule('consistent-selector-style', {
 	meta: {
 		docs: {
@@ -63,9 +75,24 @@ export default createRule('consistent-selector-style', {
 		const style = context.options[0]?.style ?? ['type', 'id', 'class'];
 
 		const whitelistedClasses: string[] = [];
-		const classSelections: Map<string, AST.SvelteHTMLElement[]> = new Map();
-		const idSelections: Map<string, AST.SvelteHTMLElement[]> = new Map();
-		const typeSelections: Map<string, AST.SvelteHTMLElement[]> = new Map();
+
+		const selections: {
+			class: Selections;
+			id: Selections;
+			type: Map<string, AST.SvelteHTMLElement[]>;
+		} = {
+			class: {
+				exact: new Map(),
+				affixes: new Map(),
+				universalSelector: false
+			},
+			id: {
+				exact: new Map(),
+				affixes: new Map(),
+				universalSelector: false
+			},
+			type: new Map()
+		};
 
 		/**
 		 * Checks selectors in a given PostCSS node
@@ -110,10 +137,10 @@ export default createRule('consistent-selector-style', {
 		 * Checks a class selector
 		 */
 		function checkClassSelector(node: SelectorClass): void {
-			if (whitelistedClasses.includes(node.value)) {
+			if (selections.class.universalSelector || whitelistedClasses.includes(node.value)) {
 				return;
 			}
-			const selection = classSelections.get(node.value) ?? [];
+			const selection = matchSelection(selections.class, node.value);
 			for (const styleValue of style) {
 				if (styleValue === 'class') {
 					return;
@@ -125,7 +152,7 @@ export default createRule('consistent-selector-style', {
 					});
 					return;
 				}
-				if (styleValue === 'type' && canUseTypeSelector(selection, typeSelections)) {
+				if (styleValue === 'type' && canUseTypeSelector(selection, selections.type)) {
 					context.report({
 						messageId: 'classShouldBeType',
 						loc: styleSelectorNodeLoc(node) as AST.SourceLocation
@@ -139,7 +166,10 @@ export default createRule('consistent-selector-style', {
 		 * Checks an ID selector
 		 */
 		function checkIdSelector(node: SelectorIdentifier): void {
-			const selection = idSelections.get(node.value) ?? [];
+			if (selections.id.universalSelector) {
+				return;
+			}
+			const selection = matchSelection(selections.id, node.value);
 			for (const styleValue of style) {
 				if (styleValue === 'class') {
 					context.report({
@@ -151,7 +181,7 @@ export default createRule('consistent-selector-style', {
 				if (styleValue === 'id') {
 					return;
 				}
-				if (styleValue === 'type' && canUseTypeSelector(selection, typeSelections)) {
+				if (styleValue === 'type' && canUseTypeSelector(selection, selections.type)) {
 					context.report({
 						messageId: 'idShouldBeType',
 						loc: styleSelectorNodeLoc(node) as AST.SourceLocation
@@ -165,7 +195,7 @@ export default createRule('consistent-selector-style', {
 		 * Checks a type selector
 		 */
 		function checkTypeSelector(node: SelectorTag): void {
-			const selection = typeSelections.get(node.value) ?? [];
+			const selection = selections.type.get(node.value) ?? [];
 			for (const styleValue of style) {
 				if (styleValue === 'class') {
 					context.report({
@@ -192,21 +222,39 @@ export default createRule('consistent-selector-style', {
 				if (node.kind !== 'html') {
 					return;
 				}
-				addToArrayMap(typeSelections, node.name.name, node);
-				const classes = node.startTag.attributes.flatMap(findClassesInAttribute);
-				for (const className of classes) {
-					addToArrayMap(classSelections, className, node);
-				}
+				addToArrayMap(selections.type, node.name.name, node);
 				for (const attribute of node.startTag.attributes) {
 					if (attribute.type === 'SvelteDirective' && attribute.kind === 'Class') {
 						whitelistedClasses.push(attribute.key.name.name);
 					}
-					if (attribute.type !== 'SvelteAttribute' || attribute.key.name !== 'id') {
+					for (const className of findClassesInAttribute(attribute)) {
+						addToArrayMap(selections.class.exact, className, node);
+					}
+					if (attribute.type !== 'SvelteAttribute') {
 						continue;
 					}
 					for (const value of attribute.value) {
-						if (value.type === 'SvelteLiteral') {
-							addToArrayMap(idSelections, value.value, node);
+						if (attribute.key.name === 'class' && value.type === 'SvelteMustacheTag') {
+							const prefix = extractExpressionPrefixLiteral(context, value.expression);
+							const suffix = extractExpressionSuffixLiteral(context, value.expression);
+							if (prefix === null && suffix === null) {
+								selections.class.universalSelector = true;
+							} else {
+								addToArrayMap(selections.class.affixes, [prefix, suffix], node);
+							}
+						}
+						if (attribute.key.name === 'id') {
+							if (value.type === 'SvelteLiteral') {
+								addToArrayMap(selections.id.exact, value.value, node);
+							} else if (value.type === 'SvelteMustacheTag') {
+								const prefix = extractExpressionPrefixLiteral(context, value.expression);
+								const suffix = extractExpressionSuffixLiteral(context, value.expression);
+								if (prefix === null && suffix === null) {
+									selections.id.universalSelector = true;
+								} else {
+									addToArrayMap(selections.id.affixes, [prefix, suffix], node);
+								}
+							}
 						}
 					}
 				}
@@ -228,14 +276,27 @@ export default createRule('consistent-selector-style', {
 /**
  * Helper function to add a value to a Map of arrays
  */
-function addToArrayMap(
-	map: Map<string, AST.SvelteHTMLElement[]>,
-	key: string,
+function addToArrayMap<T>(
+	map: Map<T, AST.SvelteHTMLElement[]>,
+	key: T,
 	value: AST.SvelteHTMLElement
 ): void {
 	map.set(key, (map.get(key) ?? []).concat(value));
 }
 
+/**
+ * Finds all nodes in selections that could be matched by key
+ */
+function matchSelection(selections: Selections, key: string): SvelteHTMLElement[] {
+	const selection = selections.exact.get(key) ?? [];
+	selections.affixes.forEach((nodes, [prefix, suffix]) => {
+		if ((prefix === null || key.startsWith(prefix)) && (suffix === null || key.endsWith(suffix))) {
+			selection.push(...nodes);
+		}
+	});
+	return selection;
+}
+
 /**
  * Checks whether a given selection could be obtained using an ID selector
  */
diff --git a/packages/eslint-plugin-svelte/src/rules/no-navigation-without-base.ts b/packages/eslint-plugin-svelte/src/rules/no-navigation-without-base.ts
index aaeb4c6c6..f53018607 100644
--- a/packages/eslint-plugin-svelte/src/rules/no-navigation-without-base.ts
+++ b/packages/eslint-plugin-svelte/src/rules/no-navigation-without-base.ts
@@ -3,6 +3,7 @@ import { createRule } from '../utils/index.js';
 import { ReferenceTracker } from '@eslint-community/eslint-utils';
 import { getSourceCode } from '../utils/compat.js';
 import { findVariable } from '../utils/ast-utils.js';
+import { extractExpressionPrefixVariable } from '../utils/expression-affixes.js';
 import type { RuleContext } from '../types.js';
 import type { SvelteLiteral } from 'svelte-eslint-parser/lib/ast';
 
@@ -224,87 +225,8 @@ function expressionStartsWithBase(
 	url: TSESTree.Expression,
 	basePathNames: Set<TSESTree.Identifier>
 ): boolean {
-	switch (url.type) {
-		case 'BinaryExpression':
-			return binaryExpressionStartsWithBase(context, url, basePathNames);
-		case 'Identifier':
-			return variableStartsWithBase(context, url, basePathNames);
-		case 'MemberExpression':
-			return memberExpressionStartsWithBase(url, basePathNames);
-		case 'TemplateLiteral':
-			return templateLiteralStartsWithBase(context, url, basePathNames);
-		default:
-			return false;
-	}
-}
-
-function binaryExpressionStartsWithBase(
-	context: RuleContext,
-	url: TSESTree.BinaryExpression,
-	basePathNames: Set<TSESTree.Identifier>
-): boolean {
-	return (
-		url.left.type !== 'PrivateIdentifier' &&
-		expressionStartsWithBase(context, url.left, basePathNames)
-	);
-}
-
-function memberExpressionStartsWithBase(
-	url: TSESTree.MemberExpression,
-	basePathNames: Set<TSESTree.Identifier>
-): boolean {
-	return url.property.type === 'Identifier' && basePathNames.has(url.property);
-}
-
-function variableStartsWithBase(
-	context: RuleContext,
-	url: TSESTree.Identifier,
-	basePathNames: Set<TSESTree.Identifier>
-): boolean {
-	if (basePathNames.has(url)) {
-		return true;
-	}
-	const variable = findVariable(context, url);
-	if (
-		variable === null ||
-		variable.identifiers.length !== 1 ||
-		variable.identifiers[0].parent.type !== 'VariableDeclarator' ||
-		variable.identifiers[0].parent.init === null
-	) {
-		return false;
-	}
-	return expressionStartsWithBase(context, variable.identifiers[0].parent.init, basePathNames);
-}
-
-function templateLiteralStartsWithBase(
-	context: RuleContext,
-	url: TSESTree.TemplateLiteral,
-	basePathNames: Set<TSESTree.Identifier>
-): boolean {
-	const startingIdentifier = extractLiteralStartingExpression(url);
-	return (
-		startingIdentifier !== undefined &&
-		expressionStartsWithBase(context, startingIdentifier, basePathNames)
-	);
-}
-
-function extractLiteralStartingExpression(
-	templateLiteral: TSESTree.TemplateLiteral
-): TSESTree.Expression | undefined {
-	const literalParts = [...templateLiteral.expressions, ...templateLiteral.quasis].sort((a, b) =>
-		a.range[0] < b.range[0] ? -1 : 1
-	);
-	for (const part of literalParts) {
-		if (part.type === 'TemplateElement' && part.value.raw === '') {
-			// Skip empty quasi in the begining
-			continue;
-		}
-		if (part.type !== 'TemplateElement') {
-			return part;
-		}
-		return undefined;
-	}
-	return undefined;
+	const prefixVariable = extractExpressionPrefixVariable(context, url);
+	return prefixVariable !== null && basePathNames.has(prefixVariable);
 }
 
 function expressionIsEmpty(url: TSESTree.Expression): boolean {
diff --git a/packages/eslint-plugin-svelte/src/utils/expression-affixes.ts b/packages/eslint-plugin-svelte/src/utils/expression-affixes.ts
new file mode 100644
index 000000000..6c960746b
--- /dev/null
+++ b/packages/eslint-plugin-svelte/src/utils/expression-affixes.ts
@@ -0,0 +1,209 @@
+import type { TSESTree } from '@typescript-eslint/types';
+import { findVariable } from './ast-utils.js';
+import type { RuleContext } from '../types.js';
+import type { SvelteLiteral } from 'svelte-eslint-parser/lib/ast';
+
+// Variable prefix extraction
+
+export function extractExpressionPrefixVariable(
+	context: RuleContext,
+	expression: TSESTree.Expression
+): TSESTree.Identifier | null {
+	switch (expression.type) {
+		case 'BinaryExpression':
+			return extractBinaryExpressionPrefixVariable(context, expression);
+		case 'Identifier':
+			return extractVariablePrefixVariable(context, expression);
+		case 'MemberExpression':
+			return extractMemberExpressionPrefixVariable(expression);
+		case 'TemplateLiteral':
+			return extractTemplateLiteralPrefixVariable(context, expression);
+		default:
+			return null;
+	}
+}
+
+function extractBinaryExpressionPrefixVariable(
+	context: RuleContext,
+	expression: TSESTree.BinaryExpression
+): TSESTree.Identifier | null {
+	return expression.left.type !== 'PrivateIdentifier'
+		? extractExpressionPrefixVariable(context, expression.left)
+		: null;
+}
+
+function extractVariablePrefixVariable(
+	context: RuleContext,
+	expression: TSESTree.Identifier
+): TSESTree.Identifier | null {
+	const variable = findVariable(context, expression);
+	if (
+		variable === null ||
+		variable.identifiers.length !== 1 ||
+		variable.identifiers[0].parent.type !== 'VariableDeclarator' ||
+		variable.identifiers[0].parent.init === null
+	) {
+		return expression;
+	}
+	return (
+		extractExpressionPrefixVariable(context, variable.identifiers[0].parent.init) ?? expression
+	);
+}
+
+function extractMemberExpressionPrefixVariable(
+	expression: TSESTree.MemberExpression
+): TSESTree.Identifier | null {
+	return expression.property.type === 'Identifier' ? expression.property : null;
+}
+
+function extractTemplateLiteralPrefixVariable(
+	context: RuleContext,
+	expression: TSESTree.TemplateLiteral
+): TSESTree.Identifier | null {
+	const literalParts = [...expression.expressions, ...expression.quasis].sort((a, b) =>
+		a.range[0] < b.range[0] ? -1 : 1
+	);
+	for (const part of literalParts) {
+		if (part.type === 'TemplateElement' && part.value.raw === '') {
+			// Skip empty quasi in the begining
+			continue;
+		}
+		if (part.type !== 'TemplateElement') {
+			return extractExpressionPrefixVariable(context, part);
+		}
+		return null;
+	}
+	return null;
+}
+
+// Literal prefix extraction
+
+export function extractExpressionPrefixLiteral(
+	context: RuleContext,
+	expression: SvelteLiteral | TSESTree.Node
+): string | null {
+	switch (expression.type) {
+		case 'BinaryExpression':
+			return extractBinaryExpressionPrefixLiteral(context, expression);
+		case 'Identifier':
+			return extractVariablePrefixLiteral(context, expression);
+		case 'Literal':
+			return typeof expression.value === 'string' ? expression.value : null;
+		case 'SvelteLiteral':
+			return expression.value;
+		case 'TemplateLiteral':
+			return extractTemplateLiteralPrefixLiteral(context, expression);
+		default:
+			return null;
+	}
+}
+
+function extractBinaryExpressionPrefixLiteral(
+	context: RuleContext,
+	expression: TSESTree.BinaryExpression
+): string | null {
+	return expression.left.type !== 'PrivateIdentifier'
+		? extractExpressionPrefixLiteral(context, expression.left)
+		: null;
+}
+
+function extractVariablePrefixLiteral(
+	context: RuleContext,
+	expression: TSESTree.Identifier
+): string | null {
+	const variable = findVariable(context, expression);
+	if (
+		variable === null ||
+		variable.identifiers.length !== 1 ||
+		variable.identifiers[0].parent.type !== 'VariableDeclarator' ||
+		variable.identifiers[0].parent.init === null
+	) {
+		return null;
+	}
+	return extractExpressionPrefixLiteral(context, variable.identifiers[0].parent.init);
+}
+
+function extractTemplateLiteralPrefixLiteral(
+	context: RuleContext,
+	expression: TSESTree.TemplateLiteral
+): string | null {
+	const literalParts = [...expression.expressions, ...expression.quasis].sort((a, b) =>
+		a.range[0] < b.range[0] ? -1 : 1
+	);
+	for (const part of literalParts) {
+		if (part.type === 'TemplateElement') {
+			if (part.value.raw === '') {
+				// Skip empty quasi
+				continue;
+			}
+			return part.value.raw;
+		}
+		return extractExpressionPrefixLiteral(context, part);
+	}
+	return null;
+}
+
+// Literal suffix extraction
+
+export function extractExpressionSuffixLiteral(
+	context: RuleContext,
+	expression: SvelteLiteral | TSESTree.Node
+): string | null {
+	switch (expression.type) {
+		case 'BinaryExpression':
+			return extractBinaryExpressionSuffixLiteral(context, expression);
+		case 'Identifier':
+			return extractVariableSuffixLiteral(context, expression);
+		case 'Literal':
+			return typeof expression.value === 'string' ? expression.value : null;
+		case 'SvelteLiteral':
+			return expression.value;
+		case 'TemplateLiteral':
+			return extractTemplateLiteralSuffixLiteral(context, expression);
+		default:
+			return null;
+	}
+}
+
+function extractBinaryExpressionSuffixLiteral(
+	context: RuleContext,
+	expression: TSESTree.BinaryExpression
+): string | null {
+	return extractExpressionSuffixLiteral(context, expression.right);
+}
+
+function extractVariableSuffixLiteral(
+	context: RuleContext,
+	expression: TSESTree.Identifier
+): string | null {
+	const variable = findVariable(context, expression);
+	if (
+		variable === null ||
+		variable.identifiers.length !== 1 ||
+		variable.identifiers[0].parent.type !== 'VariableDeclarator' ||
+		variable.identifiers[0].parent.init === null
+	) {
+		return null;
+	}
+	return extractExpressionSuffixLiteral(context, variable.identifiers[0].parent.init);
+}
+
+function extractTemplateLiteralSuffixLiteral(
+	context: RuleContext,
+	expression: TSESTree.TemplateLiteral
+): string | null {
+	const literalParts = [...expression.expressions, ...expression.quasis].sort((a, b) =>
+		a.range[0] < b.range[0] ? -1 : 1
+	);
+	for (const part of literalParts.reverse()) {
+		if (part.type === 'TemplateElement') {
+			if (part.value.raw === '') {
+				// Skip empty quasi
+				continue;
+			}
+			return part.value.raw;
+		}
+		return extractExpressionSuffixLiteral(context, part);
+	}
+	return null;
+}
diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/type-id-class/class-dynamic-prefix01-input.svelte b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/type-id-class/class-dynamic-prefix01-input.svelte
new file mode 100644
index 000000000..d3437cb3b
--- /dev/null
+++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/type-id-class/class-dynamic-prefix01-input.svelte
@@ -0,0 +1,33 @@
+<script>
+  import { value } from "package";
+
+  const derived = "link-three-" + value;
+</script>
+
+<a>Click me!</a>
+
+<a class={"link-one-" + value}>Click me two!</a>
+
+<a class={"link-one-" + value}>Click me two!</a>
+
+<a class={`link-two-${value}`}>Click me three!</a>
+
+<a class={`link-two-${value}`}>Click me three!</a>
+
+<a class={derived}>Click me four!</a>
+
+<a class={derived}>Click me four!</a>
+
+<style>
+  .link-one-foo {
+    color: red;
+  }
+
+  .link-two-foo {
+    color: red;
+  }
+
+  .link-three-foo {
+    color: red;
+  }
+</style>
diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/type-id-class/class-dynamic-suffix01-input.svelte b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/type-id-class/class-dynamic-suffix01-input.svelte
new file mode 100644
index 000000000..5d6b127a3
--- /dev/null
+++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/type-id-class/class-dynamic-suffix01-input.svelte
@@ -0,0 +1,34 @@
+<script>
+  import { value } from "package";
+
+  const derived = value + "-link-three";
+</script>
+
+<a>Click me!</a>
+
+<a class={value + "-link-one"}>Click me two!</a>
+
+<a class={value + "-link-one"}>Click me two!</a>
+
+<a class={`${value}-link-two`}>Click me three!</a>
+
+<a class={`${value}-link-two`}>Click me three!</a>
+
+
+<a class={derived}>Click me four!</a>
+
+<a class={derived}>Click me four!</a>
+
+<style>
+  .foo-link-one {
+    color: red;
+  }
+
+  .foo-link-two {
+    color: red;
+  }
+
+  .foo-link-three {
+    color: red;
+  }
+</style>
diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/type-id-class/class-dynamic-universal01-input.svelte b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/type-id-class/class-dynamic-universal01-input.svelte
new file mode 100644
index 000000000..72ea834f2
--- /dev/null
+++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/type-id-class/class-dynamic-universal01-input.svelte
@@ -0,0 +1,23 @@
+<script>
+  import { value } from "package";
+</script>
+
+<a>Click me!</a>
+
+<a class={value}>Click me two!</a>
+
+<a class={value}>Click me two!</a>
+
+<style>
+  .link-one {
+    color: red;
+  }
+
+  .link-two {
+    color: red;
+  }
+
+  .link-three {
+    color: red;
+  }
+</style>
diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/type-id-class/id-dynamic-prefix01-input.svelte b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/type-id-class/id-dynamic-prefix01-input.svelte
new file mode 100644
index 000000000..3e6743a71
--- /dev/null
+++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/type-id-class/id-dynamic-prefix01-input.svelte
@@ -0,0 +1,27 @@
+<script>
+  import { value } from "package";
+
+  const derived = "link-three-" + value;
+</script>
+
+<a>Click me!</a>
+
+<a id={"link-one-" + value}>Click me two!</a>
+
+<a id={`link-two-${value}`}>Click me three!</a>
+
+<a id={derived}>Click me four!</a>
+
+<style>
+  #link-one-foo {
+    color: red;
+  }
+
+  #link-two-foo {
+    color: red;
+  }
+
+  #link-three-foo {
+    color: red;
+  }
+</style>
diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/type-id-class/id-dynamic-suffix01-input.svelte b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/type-id-class/id-dynamic-suffix01-input.svelte
new file mode 100644
index 000000000..dc701edaf
--- /dev/null
+++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/type-id-class/id-dynamic-suffix01-input.svelte
@@ -0,0 +1,27 @@
+<script>
+  import { value } from "package";
+
+  const derived = value + "-link-three";
+</script>
+
+<a>Click me!</a>
+
+<a id={value + "-link-one"}>Click me two!</a>
+
+<a id={`${value}-link-two`}>Click me three!</a>
+
+<a id={derived}>Click me four!</a>
+
+<style>
+  #foo-link-one {
+    color: red;
+  }
+
+  #foo-link-two {
+    color: red;
+  }
+
+  #foo-link-three {
+    color: red;
+  }
+</style>
diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/type-id-class/id-dynamic-universal01-input.svelte b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/type-id-class/id-dynamic-universal01-input.svelte
new file mode 100644
index 000000000..457936530
--- /dev/null
+++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/type-id-class/id-dynamic-universal01-input.svelte
@@ -0,0 +1,23 @@
+<script>
+  import { value } from "package";
+</script>
+
+<a>Click me!</a>
+
+<a id={value}>Click me two!</a>
+
+<a id={value}>Click me two!</a>
+
+<style>
+  #link-one {
+    color: red;
+  }
+
+  #link-two {
+    color: red;
+  }
+
+  #link-three {
+    color: red;
+  }
+</style>