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() 메소드를 사용한다.

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

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

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

이벤트 핸들링

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

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

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

2. CSS와의 통합

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

인라인 스타일 적용

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

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

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

CSS 클래스 적용

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

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

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

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

3. 외부 CSS 파일과의 연동

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

CSS 파일 링크

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

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

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

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

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

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

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

CSS 변수 정의

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

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

CSS 변수 사용

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

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

Dart에서 CSS 변수 변경

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

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

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

5. Dart와 Shadow DOM

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

Shadow DOM 생성

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

// 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로 작성할 수 있다.

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

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

button.style.backgroundColor = 'blue';

CSS 애니메이션

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

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

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

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

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

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

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

Flexbox 활용

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

.container {
  display: flex;
  justify-content: space-between;
}
<div class="container">
  <button>Button 1</button>
  <button>Button 2</button>
  <button>Button 3</button>
</div>

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

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

CSS Grid 활용

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

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

.grid-item {
  background-color: lightblue;
  padding: 20px;
  text-align: center;
}
<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 속성을 동적으로 변경할 수 있다.

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

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

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

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

미디어 쿼리 정의

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

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

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

Dart에서 미디어 쿼리 사용

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

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의 기본 구조를 미리 정의할 수 있다.

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

Dart에서 Template 복제 및 추가

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

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

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

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