diff --git a/CHANGELOG.md b/CHANGELOG.md
index d2d9a629..b1a32dba 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,7 @@
+# Unreleased
+
+- Add support for `Touch` for emscripten backend.
+
 # Version 0.9.0 (2017-12-01)
 
 - Added event `WindowEvent::HiDPIFactorChanged`.
diff --git a/src/platform/emscripten/ffi.rs b/src/platform/emscripten/ffi.rs
index 8f5457cf..65291a92 100644
--- a/src/platform/emscripten/ffi.rs
+++ b/src/platform/emscripten/ffi.rs
@@ -91,6 +91,11 @@ pub type em_fullscreenchange_callback_func = Option<unsafe extern "C" fn(
     fullscreenChangeEvent: *const EmscriptenFullscreenChangeEvent,
     userData: *mut c_void) -> EM_BOOL>;
 
+pub type em_touch_callback_func = Option<unsafe extern "C" fn(
+    eventType: c_int,
+    touchEvent: *const EmscriptenTouchEvent,
+    userData: *mut c_void) -> EM_BOOL>;
+
 #[repr(C)]
 pub struct EmscriptenFullscreenChangeEvent {
     pub isFullscreen: c_int,
@@ -162,6 +167,45 @@ fn bindgen_test_layout_EmscriptenMouseEvent() {
     assert_eq!(mem::align_of::<EmscriptenMouseEvent>(), 8usize);
 }
 
+#[repr(C)]
+#[derive(Debug, Copy, Clone)]
+pub struct EmscriptenTouchPoint {
+    pub identifier: c_long,
+    pub screenX: c_long,
+    pub screenY: c_long,
+    pub clientX: c_long,
+    pub clientY: c_long,
+    pub pageX: c_long,
+    pub pageY: c_long,
+    pub isChanged: c_int,
+    pub onTarget: c_int,
+    pub targetX: c_long,
+    pub targetY: c_long,
+    pub canvasX: c_long,
+    pub canvasY: c_long,
+}
+#[test]
+fn bindgen_test_layout_EmscriptenTouchPoint() {
+    assert_eq!(mem::size_of::<EmscriptenTouchPoint>(), 96usize);
+    assert_eq!(mem::align_of::<EmscriptenTouchPoint>(), 8usize);
+}
+
+#[repr(C)]
+#[derive(Debug, Copy, Clone)]
+pub struct EmscriptenTouchEvent {
+    pub numTouches: c_int,
+    pub ctrlKey: c_int,
+    pub shiftKey: c_int,
+    pub altKey: c_int,
+    pub metaKey: c_int,
+    pub touches: [EmscriptenTouchPoint; 32usize],
+}
+#[test]
+fn bindgen_test_layout_EmscriptenTouchEvent() {
+    assert_eq!(mem::size_of::<EmscriptenTouchEvent>(), 3096usize);
+    assert_eq!(mem::align_of::<EmscriptenTouchEvent>(), 8usize);
+}
+
 #[repr(C)]
 pub struct EmscriptenPointerlockChangeEvent {
     pub isActive: c_int,
@@ -238,4 +282,24 @@ extern "C" {
         func: em_callback_func, fps: c_int, simulate_infinite_loop: EM_BOOL);
 
     pub fn emscripten_cancel_main_loop();
+
+    pub fn emscripten_set_touchstart_callback(
+        target: *const c_char, userData: *mut c_void,
+        useCapture: c_int, callback: em_touch_callback_func)
+        -> EMSCRIPTEN_RESULT;
+
+    pub fn emscripten_set_touchend_callback(
+        target: *const c_char, userData: *mut c_void,
+        useCapture: c_int, callback: em_touch_callback_func)
+        -> EMSCRIPTEN_RESULT;
+
+    pub fn emscripten_set_touchmove_callback(
+        target: *const c_char, userData: *mut c_void,
+        useCapture: c_int, callback: em_touch_callback_func)
+        -> EMSCRIPTEN_RESULT;
+
+    pub fn emscripten_set_touchcancel_callback(
+        target: *const c_char, userData: *mut c_void,
+        useCapture: c_int, callback: em_touch_callback_func)
+        -> EMSCRIPTEN_RESULT;
 }
diff --git a/src/platform/emscripten/mod.rs b/src/platform/emscripten/mod.rs
index 268bca9a..9b3bd131 100644
--- a/src/platform/emscripten/mod.rs
+++ b/src/platform/emscripten/mod.rs
@@ -274,6 +274,40 @@ extern "C" fn keyboard_callback(
     ffi::EM_FALSE
 }
 
+extern fn touch_callback(
+    event_type: c_int,
+    event: *const ffi::EmscriptenTouchEvent,
+    event_queue: *mut c_void) -> ffi::EM_BOOL
+{
+    unsafe {
+        let queue: &RefCell<VecDeque<::Event>> = mem::transmute(event_queue);
+
+        let phase = match event_type {
+            ffi::EMSCRIPTEN_EVENT_TOUCHSTART => ::TouchPhase::Started,
+            ffi::EMSCRIPTEN_EVENT_TOUCHEND => ::TouchPhase::Ended,
+            ffi::EMSCRIPTEN_EVENT_TOUCHMOVE => ::TouchPhase::Moved,
+            ffi::EMSCRIPTEN_EVENT_TOUCHCANCEL => ::TouchPhase::Cancelled,
+            _ => return ffi::EM_FALSE,
+        };
+
+        for touch in 0..(*event).numTouches as usize {
+            let touch = (*event).touches[touch];
+            if touch.isChanged == ffi::EM_TRUE {
+                queue.borrow_mut().push_back(::Event::WindowEvent {
+                    window_id: ::WindowId(WindowId(0)),
+                    event: ::WindowEvent::Touch(::Touch {
+                        device_id: ::DeviceId(DeviceId),
+                        phase,
+                        id: touch.identifier as u64,
+                        location: (touch.canvasX as f64, touch.canvasY as f64),
+                    }),
+                });
+            }
+        }
+    }
+    ffi::EM_FALSE
+}
+
 // In case of fullscreen window this method will request fullscreen on change
 #[allow(non_snake_case)]
 unsafe extern "C" fn fullscreen_callback(
@@ -335,6 +369,14 @@ impl Window {
                 .map_err(|e| ::CreationError::OsError(format!("emscripten error: {}", e)))?;
             em_try(ffi::emscripten_set_keyup_callback(DOCUMENT_NAME.as_ptr() as *const c_char, mem::transmute(&*window.window.events), ffi::EM_FALSE, Some(keyboard_callback)))
                 .map_err(|e| ::CreationError::OsError(format!("emscripten error: {}", e)))?;
+            em_try(ffi::emscripten_set_touchstart_callback(DOCUMENT_NAME.as_ptr() as *const c_char, mem::transmute(&*window.window.events), ffi::EM_FALSE, Some(touch_callback)))
+                .map_err(|e| ::CreationError::OsError(format!("emscripten error: {}", e)))?;
+            em_try(ffi::emscripten_set_touchend_callback(DOCUMENT_NAME.as_ptr() as *const c_char, mem::transmute(&*window.window.events), ffi::EM_FALSE, Some(touch_callback)))
+                .map_err(|e| ::CreationError::OsError(format!("emscripten error: {}", e)))?;
+            em_try(ffi::emscripten_set_touchmove_callback(DOCUMENT_NAME.as_ptr() as *const c_char, mem::transmute(&*window.window.events), ffi::EM_FALSE, Some(touch_callback)))
+                .map_err(|e| ::CreationError::OsError(format!("emscripten error: {}", e)))?;
+            em_try(ffi::emscripten_set_touchcancel_callback(DOCUMENT_NAME.as_ptr() as *const c_char, mem::transmute(&*window.window.events), ffi::EM_FALSE, Some(touch_callback)))
+                .map_err(|e| ::CreationError::OsError(format!("emscripten error: {}", e)))?;
         }
 
         if attribs.fullscreen.is_some() {