# HTML 및 CSS와의 통합

Dart에서 웹 애플리케이션을 개발할 때, HTML과 CSS를 함께 사용하는 것은 매우 중요한 부분이다. Dart는 웹 개발을 위해 **dart:html** 패키지를 제공하며, 이를 통해 HTML 문서와의 상호작용을 원활하게 할 수 있다. 또한, CSS를 사용하여 스타일링을 적용하고 UI의 외관을 조정할 수 있다.

### 1. HTML 요소와 Dart의 상호작용

Dart에서 HTML 요소를 선택하고 조작하는 방식은 JavaScript와 유사한다. Dart의 **dart:html** 패키지를 사용하면 DOM(Document Object Model)에 접근하고 HTML 요소를 조작할 수 있다.

#### HTML 요소 선택

HTML 요소를 Dart에서 선택하기 위해서는 **querySelector()** 또는 **querySelectorAll()** 메소드를 사용한다.

```dart
// 단일 요소 선택
var button = querySelector('#myButton');

// 다중 요소 선택
var items = querySelectorAll('.item');
```

이 함수들은 각각 특정 ID 또는 클래스를 가진 HTML 요소를 선택하고, 이를 Dart에서 변수에 저장하여 조작할 수 있도록 한다.

#### 이벤트 핸들링

선택된 HTML 요소에 이벤트 핸들러를 추가하여 사용자와의 상호작용을 처리할 수 있다. 예를 들어, 버튼 클릭 이벤트를 처리하는 방법은 다음과 같다.

```dart
// 버튼 클릭 이벤트 처리
button.onClick.listen((event) {
  print('Button clicked!');
});
```

이와 같이, **onClick**, **onChange** 등 다양한 이벤트 리스너를 추가하여 사용자의 입력에 반응하는 동적인 웹 애플리케이션을 개발할 수 있다.

### 2. CSS와의 통합

Dart에서는 **Element** 객체의 **style** 속성을 사용하여 CSS 스타일을 직접 조작할 수 있다. 이를 통해 JavaScript에서와 마찬가지로 CSS를 다룰 수 있다.

#### 인라인 스타일 적용

HTML 요소에 인라인 스타일을 적용하는 방법은 다음과 같다.

```dart
// 요소에 인라인 스타일 적용
button.style.backgroundColor = 'blue';
button.style.color = 'white';
```

이 코드를 실행하면 선택된 버튼의 배경색이 파란색으로, 텍스트 색상이 흰색으로 변경된다.

#### CSS 클래스 적용

Dart에서는 **classList** 속성을 사용하여 HTML 요소에 CSS 클래스를 추가하거나 제거할 수 있다.

```dart
// 클래스 추가
button.classes.add('active');

// 클래스 제거
button.classes.remove('inactive');
```

이와 같은 방식으로 CSS 클래스를 동적으로 조작하여 HTML 요소의 스타일을 변경할 수 있다.

### 3. 외부 CSS 파일과의 연동

Dart 애플리케이션에서도 외부 CSS 파일을 연동하여 사용할 수 있다. HTML 파일에서 CSS 파일을 링크하는 방식은 일반적인 HTML과 동일하며, Dart 코드에서는 해당 CSS 클래스를 활용하여 스타일을 적용하거나 변경할 수 있다.

#### CSS 파일 링크

HTML 파일에서 외부 CSS 파일을 링크하는 방법은 다음과 같다.

```html
<head>
  <link rel="stylesheet" href="styles.css">
</head>
```

이렇게 CSS 파일을 HTML 문서에 포함한 후, Dart에서 **classList**를 사용하여 CSS 클래스를 추가하거나 제거할 수 있다.

```dart
// 요소에 외부 CSS 클래스 적용
button.classes.add('btn-primary');
```

위 코드는 **styles.css** 파일에서 정의된 **btn-primary** 클래스를 적용하여 버튼의 스타일을 변경한다.

### 4. CSS 변수를 사용한 스타일 조작

CSS 변수(Custom Properties)를 사용하면 웹 페이지의 스타일을 더 동적으로 제어할 수 있다. CSS 변수를 활용하면 Dart에서 특정 변수를 변경하여 전체 스타일에 영향을 미칠 수 있다.

#### CSS 변수 정의

먼저 CSS에서 변수를 정의한다.

```css
:root {
  --main-bg-color: #ff0000;
}
```

#### CSS 변수 사용

정의된 CSS 변수를 사용할 수 있다.

```css
button {
  background-color: var(--main-bg-color);
}
```

#### Dart에서 CSS 변수 변경

Dart 코드에서 CSS 변수를 변경하려면 **document.documentElement.style.setProperty()** 메소드를 사용한다.

```dart
// CSS 변수 변경
document.documentElement.style.setProperty('--main-bg-color', '#0000ff');
```

이 코드를 실행하면 페이지의 CSS 변수가 변경되며, 버튼의 배경색이 빨간색에서 파란색으로 변하게 된다.

### 5. Dart와 Shadow DOM

Shadow DOM은 웹 컴포넌트의 핵심 기술로, Dart에서도 이를 활용하여 DOM 구조를 캡슐화할 수 있다. 이를 통해 각 컴포넌트가 독립적인 스타일과 DOM 구조를 유지할 수 있다.

#### Shadow DOM 생성

Dart에서 Shadow DOM을 생성하는 방법은 다음과 같다.

```dart
// Shadow DOM 생성
var shadowRoot = querySelector('#my-element').attachShadow({'mode': 'open'});

// Shadow DOM에 HTML 및 스타일 추가
shadowRoot.innerHtml = '''
  <style>
    p {
      color: red;
    }
  </style>
  <p>Shadow DOM content</p>
''';
```

위 코드에서는 **attachShadow()** 메소드를 사용하여 Shadow DOM을 생성하고, 그 안에 HTML 및 CSS를 추가한다.

Shadow DOM을 사용하면 스타일이 외부에서 영향을 받지 않으므로, 캡슐화된 웹 컴포넌트를 만들 수 있다.

### 6. CSS Transitions와 Animations

Dart에서 CSS 애니메이션과 전환(Transition)을 다룰 때도, CSS 규칙을 사용하여 스타일 변경에 애니메이션 효과를 부여할 수 있다. Dart를 활용하여 애니메이션의 트리거를 제어할 수 있다.

#### CSS 전환 사용

CSS 전환을 사용하면 스타일 속성의 변화가 서서히 적용되도록 만들 수 있다. 예를 들어, 버튼의 색상을 전환하는 코드를 CSS로 작성할 수 있다.

```css
button {
  transition: background-color 0.5s ease;
}
```

Dart에서 버튼의 색상을 변경하면, 전환 효과가 적용되어 부드럽게 변한다.

```dart
button.style.backgroundColor = 'blue';
```

#### CSS 애니메이션

CSS 애니메이션을 정의하고 이를 Dart에서 트리거할 수도 있다.

```css
@keyframes fadeIn {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}

button {
  animation: fadeIn 1s ease-in;
}
```

Dart 코드를 통해 특정 이벤트에서 애니메이션을 활성화할 수 있다.

```dart
button.onClick.listen((event) {
  button.classes.add('fade-in');
});
```

### 7. CSS Grid와 Flexbox를 통한 레이아웃 조정

Dart와 HTML/CSS를 결합하여 웹 애플리케이션의 레이아웃을 동적으로 조정할 수 있다. 특히, **CSS Grid**와 **Flexbox**는 레이아웃을 쉽게 조정할 수 있는 두 가지 강력한 도구이다. 이들 기술을 사용하면 Dart에서 레이아웃을 다루는 것이 훨씬 더 유연하고 직관적이다.

#### Flexbox 활용

**Flexbox**는 컨테이너 안의 요소들을 유연하게 배치하는 방법을 제공한다. 아래는 Flexbox를 사용하여 세 개의 버튼을 가로로 배치하는 예시이다.

```css
.container {
  display: flex;
  justify-content: space-between;
}
```

```html
<div class="container">
  <button>Button 1</button>
  <button>Button 2</button>
  <button>Button 3</button>
</div>
```

Dart에서는 Flexbox와 같은 레이아웃 스타일을 동적으로 적용할 수 있다.

```dart
var container = querySelector('.container');
container.style.display = 'flex';
container.style.justifyContent = 'space-between';
```

#### CSS Grid 활용

**CSS Grid**는 더 복잡한 레이아웃을 관리하는 데 적합한 기술이다. 이를 통해 여러 행과 열로 구성된 레이아웃을 쉽게 정의할 수 있다.

```css
.grid-container {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-gap: 10px;
}

.grid-item {
  background-color: lightblue;
  padding: 20px;
  text-align: center;
}
```

```html
<div class="grid-container">
  <div class="grid-item">Item 1</div>
  <div class="grid-item">Item 2</div>
  <div class="grid-item">Item 3</div>
</div>
```

Dart를 사용하여 **grid-template-columns**와 같은 CSS 속성을 동적으로 변경할 수 있다.

```dart
var gridContainer = querySelector('.grid-container');
gridContainer.style.gridTemplateColumns = 'repeat(4, 1fr)';
```

위 코드를 통해 레이아웃이 3열에서 4열로 동적으로 변경된다. 이처럼 Dart는 CSS Grid를 통해 복잡한 레이아웃을 동적으로 조정할 수 있다.

### 8. 반응형 디자인 (Responsive Design)

반응형 디자인은 다양한 화면 크기에서 일관된 UI 경험을 제공하기 위해 중요한 부분이다. CSS의 **미디어 쿼리**를 사용하여 화면 크기에 따라 레이아웃이나 스타일을 동적으로 조정할 수 있다.

#### 미디어 쿼리 정의

미디어 쿼리는 CSS에서 다음과 같이 정의된다.

```css
@media (max-width: 600px) {
  .container {
    flex-direction: column;
  }
}
```

이 코드에서는 화면의 너비가 600px 이하일 때, **Flexbox** 컨테이너의 방향이 가로에서 세로로 변경된다.

#### Dart에서 미디어 쿼리 사용

Dart에서 화면 크기를 감지하고 이를 통해 반응형 스타일을 동적으로 적용할 수 있다. **window\.matchMedia** 메소드를 사용하여 미디어 쿼리를 감지할 수 있다.

```dart
if (window.matchMedia('(max-width: 600px)').matches) {
  container.style.flexDirection = 'column';
} else {
  container.style.flexDirection = 'row';
}
```

이 코드는 화면 크기에 따라 Flexbox의 방향을 변경하는 예시이다. Dart와 미디어 쿼리를 결합하여 반응형 디자인을 쉽게 구현할 수 있다.

### 9. HTML Template 활용

**HTML Template** 태그를 사용하면 미리 정의된 HTML 구조를 Dart 코드에서 동적으로 추가할 수 있다. 이는 동적인 UI 요소를 추가하거나 제거할 때 유용하게 사용할 수 있다.

#### Template 태그 정의

HTML에서 **template** 태그를 사용하여 UI의 기본 구조를 미리 정의할 수 있다.

```html
<template id="my-template">
  <div class="template-item">
    <p>Template Content</p>
  </div>
</template>
```

#### Dart에서 Template 복제 및 추가

Dart 코드에서는 **importNode()** 메소드를 사용하여 템플릿의 내용을 복제하고 DOM에 추가할 수 있다.

```dart
var template = querySelector('#my-template') as TemplateElement;
var content = document.importNode(template.content, true);

// DOM에 템플릿 추가
document.body.append(content);
```

이 코드를 통해 **template** 태그 내의 내용을 복제하여 원하는 위치에 삽입할 수 있다.
